This commit is contained in:
zpc 2024-10-31 00:02:27 +08:00
parent bc92bdeab2
commit 79a69db7d8
9 changed files with 304 additions and 26 deletions

View File

@ -1,4 +1,5 @@
using CloudGaming.Api.Base; using CloudGaming.Api.Base;
using CloudGaming.DtoModel;
using CloudGaming.GameModel.Db.Db_Ext; using CloudGaming.GameModel.Db.Db_Ext;
using HuanMeng.DotNetCore.Base; using HuanMeng.DotNetCore.Base;
@ -22,9 +23,11 @@ namespace CloudGaming.Api.Controllers
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public async Task<dynamic> GetAppConfigAsync() public async Task<AppConfigDto> GetAppConfigAsync()
{ {
return new { test = "测试", Data = new { txt = "内部数据" } }; AppConfigDto appConfigDto = new AppConfigDto();
appConfigDto.AppConfigExtend = new AppConfigExtend();
return appConfigDto;
} }
/// <summary> /// <summary>

View File

@ -69,6 +69,15 @@
"refreshTokenExpiration": 10100 "refreshTokenExpiration": 10100
}, },
"AgileConfig": {
"appId": "CloudGaming",
"secret": "95BB717C61D1ECB0E9FB82C932CC77FF",
"nodes": "http://124.220.55.158:94", //使
"url": "http://124.220.55.158:94",
"env": "DEV",
"UserName": "admin",
"Password": "dbt@com@1234"
},
// //
"Kestrel": { "Kestrel": {
"Endpoints": { "Endpoints": {

View File

@ -1,5 +1,9 @@
using AgileConfig.Client;
using CloudGaming.Code.DataAccess.MultiTenantUtil; using CloudGaming.Code.DataAccess.MultiTenantUtil;
using HuanMeng.DotNetCore.CacheHelper;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Frozen; using System.Collections.Frozen;
@ -44,6 +48,31 @@ namespace CloudGaming.Code.AppExtend
return AppConfigs.FirstOrDefault().Value; return AppConfigs.FirstOrDefault().Value;
} }
/// <summary>
///
/// </summary>
/// <param name="args"></param>
public static void ConfigClient_ConfigChanged(ConfigReloadedArgs args)
{
if (args.OldConfigs.TryGetValue("Version", out var vresion) && args.NewConfigs.TryGetValue("Version", out var newVersion))
{
if (vresion != newVersion)
{
MemoryCacheHelper.cache.Clear();
}
}
VerifyTenant(args);
//if (VerifyTenant(args, "Payment:WeChatConfig"))
//{
// PaymentExtend.AddWeChat(ConfigurationManager);
//}
//if (VerifyTenant(args, "Payment:AlipayConfig"))
//{
// PaymentExtend.AddAlipay(ConfigurationManager);
//}
}
/// <summary> /// <summary>
@ -51,12 +80,11 @@ namespace CloudGaming.Code.AppExtend
/// </summary> /// </summary>
/// <param name="builder"></param> /// <param name="builder"></param>
/// <returns></returns> /// <returns></returns>
public static IHostApplicationBuilder AddAppConfigClient(this IHostApplicationBuilder builder) public static IHostApplicationBuilder AddAppConfigClient(this WebApplicationBuilder builder)
{ {
//hostBuilder. var configClient = new ConfigClient(builder.Configuration);
//builder..UseAgileConfig(configClient, ConfigClient_ConfigChanged); builder.Host.UseAgileConfig(configClient, ConfigClient_ConfigChanged);
//AppConfigClient = configClient;
ConfigurationManager = builder.Configuration; ConfigurationManager = builder.Configuration;
AppConfigInit(builder.Configuration); AppConfigInit(builder.Configuration);
builder.Services.AddScoped<AppConfig>(); builder.Services.AddScoped<AppConfig>();
@ -137,6 +165,41 @@ namespace CloudGaming.Code.AppExtend
return newAppConfig; return newAppConfig;
} }
/// <summary>
/// 验证多租户
/// </summary>
/// <param name="args"></param>
private static bool VerifyTenant(ConfigReloadedArgs args, string key)
{
var newTenant = args.NewConfigs.Where(it => it.Key.Contains(key)).ToDictionary();
var oldTenant = args.OldConfigs.Where(it => it.Key.Contains(key)).ToDictionary();
bool areEqual = newTenant.Count == oldTenant.Count &&
!newTenant.Except(oldTenant).Any();
if (!areEqual)
{
//更新缓存
//AppConfigInit(ConfigurationManager);
return true;
}
return false;
}
/// <summary>
/// 验证多租户
/// </summary>
/// <param name="args"></param>
private static void VerifyTenant(ConfigReloadedArgs args)
{
var newTenant = args.NewConfigs.Where(it => it.Key.Contains("Tenants")).ToDictionary();
var oldTenant = args.OldConfigs.Where(it => it.Key.Contains("Tenants")).ToDictionary();
bool areEqual = newTenant.Count == oldTenant.Count &&
!newTenant.Except(oldTenant).Any();
if (!areEqual)
{
//更新缓存
AppConfigInit(ConfigurationManager);
}
}
/// <summary> /// <summary>
/// 初始化租户数据 /// 初始化租户数据
@ -144,7 +207,7 @@ namespace CloudGaming.Code.AppExtend
/// <param name="configurationManager"></param> /// <param name="configurationManager"></param>
private static void AppConfigInit(IConfigurationManager configurationManager) private static void AppConfigInit(IConfigurationManager configurationManager)
{ {
var tenants = configurationManager.GetSection("Tenant").Get<List<AppConfig>>(); var tenants = configurationManager.GetSection("Tenants").Get<List<AppConfig>>();
if (tenants != null) if (tenants != null)
{ {
ConcurrentDictionary<string, AppConfig> _AppConfigs = new ConcurrentDictionary<string, AppConfig>(); ConcurrentDictionary<string, AppConfig> _AppConfigs = new ConcurrentDictionary<string, AppConfig>();

View File

@ -1,3 +1,5 @@
using HuanMeng.DotNetCore.AttributeExtend;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
@ -36,11 +38,90 @@ namespace CloudGaming.Code.AppExtend
{ {
} }
FindImagesAttributes(objectResult.Value);
// var responseObject = objectResult.Value;
// var membersWithImagesAttribute = responseObject.GetType()
//.GetMembers(BindingFlags.Public | BindingFlags.Instance)
//.Where(m => m.GetCustomAttribute<ImagesAttribute>() != null);
// foreach (var member in membersWithImagesAttribute)
// {
// var imagesAttribute = member.GetCustomAttribute<ImagesAttribute>();
// Console.WriteLine($"带有 [Images] 特性的成员:{member.Name}");
// Console.WriteLine($"FieldName 属性值:{imagesAttribute?.FieldName}");
// }
// 递归处理返回对象的所有属性并打印路径 // 递归处理返回对象的所有属性并打印路径
ProcessObjectProperties(objectResult.Value, user, language, path); ProcessObjectProperties(objectResult.Value, user, language, path);
} }
} }
private void FindImagesAttributes(object obj)
{
if (obj == null) return;
// 使用反射获取对象的所有公共实例属性和字段
var membersWithImagesAttribute = obj.GetType()
.GetMembers(BindingFlags.Public | BindingFlags.Instance)
.Where(m => m is PropertyInfo || m is FieldInfo);
foreach (var member in membersWithImagesAttribute)
{
// 获取并输出带有 [Images] 特性的属性或字段
var imagesAttribute = member.GetCustomAttribute<ImagesAttribute>();
if (imagesAttribute != null)
{
Console.WriteLine($"带有 [Images] 特性的成员:{member.Name}");
Console.WriteLine($"FieldName 属性值:{imagesAttribute.FieldName}");
object value = GetMemberValue(member, obj);
Console.WriteLine($"成员值:{value}");
}
// 获取成员值
var memberValue = GetMemberValue(member, obj);
// 如果成员是 IEnumerable集合类型递归处理每个元素
if (memberValue is IEnumerable enumerableValue && memberValue.GetType() != typeof(string))
{
foreach (var item in enumerableValue)
{
if (item != null && !IsSimpleType(item.GetType()))
{
FindImagesAttributes(item);
}
}
}
// 如果成员是非集合的复杂类型,递归检查其内部成员
else if (memberValue != null && !IsSimpleType(memberValue.GetType()))
{
FindImagesAttributes(memberValue);
}
}
}
private object GetMemberValue(MemberInfo member, object obj)
{
try
{
return member switch
{
PropertyInfo property when property.GetMethod?.IsStatic == false => property.GetValue(obj),
FieldInfo field when !field.IsStatic => field.GetValue(obj),
_ => null
};
}
catch (TargetParameterCountException ex)
{
Console.WriteLine($"Error retrieving value for {member.Name}: {ex.Message}");
return null;
}
}
private bool IsSimpleType(Type type)
{
return type.IsPrimitive || type.IsEnum || type == typeof(string) || type == typeof(decimal);
}
public void OnResultExecuted(ResultExecutedContext context) public void OnResultExecuted(ResultExecutedContext context)
{ {
// 可在执行完结果后处理其他逻辑 // 可在执行完结果后处理其他逻辑

View File

@ -9,6 +9,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AgileConfig.Client" Version="1.7.3" />
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />

View File

@ -0,0 +1,53 @@
using HuanMeng.DotNetCore.AttributeExtend;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.DtoModel;
/// <summary>
///
/// </summary>
public class AppConfigDto
{
/// <summary>
/// 是否版本审核中
/// </summary>
public bool IsChecking { get; set; }
/// <summary>
/// 版本审核中可玩游戏(在谷歌包的审核模式下可以玩的游戏列表)
/// </summary>
public List<string> CheckingGames = new List<string>();
/// <summary>
/// 是否开启实名认证
/// </summary>
public bool IsAuthRealName { get; set; }
/// <summary>
/// 是否是高延迟地区
/// </summary>
public bool HighDelay { get; set; }
/// <summary>
/// 开屏图
/// </summary>
[Images]
public int OpenImage { get; set; }
public AppConfigExtend AppConfigExtend { get; set; }
}
public class AppConfigExtend
{
/// <summary>
/// 开屏图
/// </summary>
[Images]
public int TestImage { get; set; }
}

View File

@ -67,9 +67,12 @@ public partial class CloudGamingCBTContext : DbContext
entity.Property(e => e.BossId) entity.Property(e => e.BossId)
.HasMaxLength(200) .HasMaxLength(200)
.HasComment("渠道号")
.UseCollation("Chinese_PRC_CI_AS"); .UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.ConfigStr) entity.Property(e => e.ConfigId).HasComment("配置值");
.HasMaxLength(2000) entity.Property(e => e.ConfigType).HasComment("配置类型");
entity.Property(e => e.ConfigValue)
.HasComment("配置值")
.UseCollation("Chinese_PRC_CI_AS"); .UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.Continent) entity.Property(e => e.Continent)
.HasMaxLength(200) .HasMaxLength(200)
@ -79,18 +82,26 @@ public partial class CloudGamingCBTContext : DbContext
.HasMaxLength(200) .HasMaxLength(200)
.HasComment("国家 例:中国") .HasComment("国家 例:中国")
.UseCollation("Chinese_PRC_CI_AS"); .UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.CreatTime).HasColumnType("datetime"); entity.Property(e => e.CreatTime)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.Desc) entity.Property(e => e.Desc)
.HasMaxLength(2000) .HasComment("备注")
.UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.ExtJson).HasComment("扩展信息");
entity.Property(e => e.IsShow).HasComment("是否启用");
entity.Property(e => e.Name)
.HasMaxLength(200)
.HasComment("配置名称")
.UseCollation("Chinese_PRC_CI_AS"); .UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.Plat) entity.Property(e => e.Plat)
.HasMaxLength(100) .HasMaxLength(100)
.IsUnicode(false) .IsUnicode(false)
.HasComment("平台。安卓还是苹果")
.UseCollation("Chinese_PRC_CI_AS"); .UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.ShowName) entity.Property(e => e.UpdateTime)
.HasMaxLength(200) .HasComment("修改时间")
.UseCollation("Chinese_PRC_CI_AS"); .HasColumnType("datetime");
entity.Property(e => e.UpdateTime).HasColumnType("datetime");
}); });

View File

@ -11,28 +11,44 @@ public partial class T_App_Config
public virtual int Id { get; set; } public virtual int Id { get; set; }
public virtual int? ConfigType { get; set; } /// <summary>
/// 配置类型
/// </summary>
public virtual int ConfigType { get; set; }
public virtual int? ConfigId { get; set; } /// <summary>
/// 配置值
/// </summary>
public virtual int ConfigId { get; set; }
public virtual bool? IsShow { get; set; } /// <summary>
/// 是否启用
public virtual string? ShowName { get; set; } /// </summary>
public virtual bool IsShow { get; set; }
/// <summary>
/// 备注
/// </summary>
public virtual string? Desc { get; set; } public virtual string? Desc { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public virtual DateTime? UpdateTime { get; set; } public virtual DateTime? UpdateTime { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime? CreatTime { get; set; } public virtual DateTime? CreatTime { get; set; }
public virtual int? ConfigNum { get; set; } /// <summary>
/// 渠道号
public virtual int? ConfigNum2 { get; set; } /// </summary>
public virtual string? ConfigStr { get; set; }
public virtual string? BossId { get; set; } public virtual string? BossId { get; set; }
/// <summary>
/// 平台。安卓还是苹果
/// </summary>
public virtual string? Plat { get; set; } public virtual string? Plat { get; set; }
/// <summary> /// <summary>
@ -44,4 +60,19 @@ public partial class T_App_Config
/// 国家 例:中国 /// 国家 例:中国
/// </summary> /// </summary>
public virtual string? CountryName { get; set; } public virtual string? CountryName { get; set; }
/// <summary>
/// 配置值
/// </summary>
public virtual string? ConfigValue { get; set; }
/// <summary>
/// 配置名称
/// </summary>
public virtual string? Name { get; set; }
/// <summary>
/// 扩展信息
/// </summary>
public virtual string? ExtJson { get; set; }
} }

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HuanMeng.DotNetCore.AttributeExtend;
/// <summary>
///
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ImagesAttribute : Attribute
{
public string FieldName { get; set; }
/// <summary>
///
/// </summary>
/// <param name="fieldName">生成字段名称</param>
// 构造函数,用于传递参数
public ImagesAttribute(string fieldName = "")
{
this.FieldName = fieldName;
}
}