From 7f5b0651d4598dc030ea857898a9d4b58048558e Mon Sep 17 00:00:00 2001 From: zpc Date: Fri, 8 Nov 2024 16:05:21 +0800 Subject: [PATCH] 1.0.0.1 --- .../Controllers/GameController.cs | 52 +++++++ .../Controllers/HomeController.cs | 2 + .../Api/CloudGaming.Api/Program.cs | 4 + .../AppExtend/AppConfigurationExtend.cs | 14 +- .../AppExtend/AppRequestConfig.cs | 9 ++ .../Cache/CloudGamingCache.cs | 2 +- .../Cache/Special/GameEntityCache.cs | 9 +- .../MultiTenantTenantMiddleware.cs | 3 +- .../Code/CloudGaming.Code/Epg/EpgExtend.cs | 10 +- .../Code/CloudGaming.Code/Game/GameBLL.cs | 64 ++++++++ .../MiddlewareExtend/MemoryCacheMiddleware.cs | 147 ++++++++++++++++++ .../MiddlewareExtend/MiddlewareExtends.cs | 45 ++++++ .../MiddlewareExtend/RedisCacheMiddleware.cs | 124 +++++++++++++++ .../CloudGaming.DtoModel/Game/GameInfoDto.cs | 40 +++++ .../CloudGaming.DtoModel/Game/GameListDto.cs | 48 ++++++ .../Utility/ObjectExtensions1.cs | 19 ++- 16 files changed, 577 insertions(+), 15 deletions(-) create mode 100644 src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MemoryCacheMiddleware.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MiddlewareExtends.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/RedisCacheMiddleware.cs create mode 100644 src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameInfoDto.cs create mode 100644 src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs new file mode 100644 index 0000000..a8ca024 --- /dev/null +++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs @@ -0,0 +1,52 @@ +using CloudGaming.Api.Base; +using CloudGaming.Code.Cache; +using CloudGaming.Code.Game; +using CloudGaming.Code.MiddlewareExtend; +using CloudGaming.DtoModel.Game; +using CloudGaming.GameModel.Db.Db_Game; + +using Microsoft.AspNetCore.Mvc; + +namespace CloudGaming.Api.Controllers +{ + /// + /// 游戏控制器 + /// + public class GameController : CloudGamingControllerBase + { + public GameController(IServiceProvider _serviceProvider) : base(_serviceProvider) + { + } + + + /// + /// 游戏类型列表 + /// + /// + [HttpGet] + [RedisCache(2, 0, 0)] + public async Task> GetGameTypeListAsync() + { + GameBLL gamebll = new GameBLL(this.ServiceProvider); + return await gamebll.GetGameTypeListAsync(); + } + + + /// + /// 根据游戏类型Id 获取游戏列表 + /// + /// + /// + [HttpGet] + [RedisCache(2, 5, 0)] + public async Task> GetGameListAsync([FromQuery] int typeId) + { + if (typeId == 0) + { + return new List(); + } + GameBLL gamebll = new GameBLL(this.ServiceProvider); + return await gamebll.GetGameListAsync(typeId); + } + } +} diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs index c4d9b0a..1f6ce5c 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs +++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs @@ -1,5 +1,6 @@ using CloudGaming.Api.Base; using CloudGaming.Code.Epg; +using CloudGaming.Code.MiddlewareExtend; using CloudGaming.DtoModel.Epg; using Microsoft.AspNetCore.JsonPatch.Internal; @@ -18,6 +19,7 @@ public class HomeController : CloudGamingControllerBase /// /// [HttpGet] + [RedisCache(1, 0, 0)] public async Task> GetHomeInfo() { EpgBLL epgBLL = new EpgBLL(ServiceProvider); diff --git a/src/CloudGaming/Api/CloudGaming.Api/Program.cs b/src/CloudGaming/Api/CloudGaming.Api/Program.cs index d95e4d1..4265974 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/Program.cs +++ b/src/CloudGaming/Api/CloudGaming.Api/Program.cs @@ -17,6 +17,7 @@ using CloudGaming.Code.AppExtend.JsonConverHelper; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.Options; using CloudGaming.GameModel.Db.Db_Ext; +using CloudGaming.Code.MiddlewareExtend; var builder = WebApplication.CreateBuilder(args); #region 日志 // Add services to the container. @@ -37,6 +38,7 @@ builder.Services.AddSingleton(typeof(ILogger), serviceProvi return loggerFactory.CreateLogger(); }); #endregion +builder.Services.AddMemoryCache(); builder.Services.AddHttpClient(); builder.Services.AddHttpContextAccessor(); //添加httpContext注入访问 #region 返回数据解析 @@ -168,6 +170,8 @@ app.MapControllers(); app.UseStaticFiles();//静态文件访问配置 //执行扩展中间件 app.UseMiddlewareAll(); +//缓存中间件 +app.UseCloudGamingMiddlewareAll(); #region 默认请求 app.MapGet("/", () => "请求成功").WithName("默认请求"); diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs index 8886451..ae0e434 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs @@ -3,6 +3,9 @@ using AgileConfig.Client; using CloudGaming.Code.DataAccess.MultiTenantUtil; using HuanMeng.DotNetCore.CacheHelper; +using HuanMeng.DotNetCore.Redis; + +using StackExchange.Redis; using System.Collections.Concurrent; using System.Collections.Frozen; @@ -136,6 +139,15 @@ namespace CloudGaming.Code.AppExtend tenantInfo.Name = appConfig.Name; return tenantInfo; } + /// + /// 获取redis缓存 + /// + /// + /// + public static IDatabase GetRedisDataBase(this AppConfig appConfig) + { + return RedisConnection.GetRedis(appConfig.RedisConnectionString); + } /// /// @@ -162,7 +174,7 @@ namespace CloudGaming.Code.AppExtend newAppConfig.GameConnectionString = appConfig.GameConnectionString; newAppConfig.ExtConnectionString = appConfig.ExtConnectionString; newAppConfig.PhoneConnectionString = appConfig.PhoneConnectionString; - newAppConfig.AliyunConfig= appConfig.AliyunConfig; + newAppConfig.AliyunConfig = appConfig.AliyunConfig; newAppConfig.DefaultLanguage = appConfig.DefaultLanguage; return newAppConfig; } diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs index 1a534da..41df7bf 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs @@ -110,6 +110,15 @@ namespace CloudGaming.Code.AppExtend } } + /// + /// 获取key + /// + public string Key + { + + get => $"{Language}_{Channel}_{Version}"; + } + /// /// 地区 /// diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs index 1941333..c95a720 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs @@ -71,7 +71,7 @@ namespace CloudGaming.Code.Cache #endregion - public GameEntityCache? gameEntityCache; + private GameEntityCache? gameEntityCache; /// /// 游戏缓存 diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs index 9e04edd..c90abf1 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs @@ -27,7 +27,8 @@ namespace CloudGaming.Code.Cache.Special public override string key => $"{appConfig.Identifier}:game:gameInfo"; - public string locaKey => $"{appConfig.Identifier}:lock:gameInfo"; + public string locaKey => $"lock:gameInfo"; + public string RedisKey => $"cache:game:gameInfo"; public override List GetDataList() { @@ -71,10 +72,10 @@ namespace CloudGaming.Code.Cache.Special return _dataList; } - long hashLength = database.HashLength(key); + long hashLength = database.HashLength(RedisKey); if (hashLength > 0) { - var hashEntries = database.HashGetAll(key); + var hashEntries = database.HashGetAll(RedisKey); var list = hashEntries .Where(entry => !string.IsNullOrEmpty(entry.Value)) .Select(entry => JsonConvert.DeserializeObject(entry.Value)) @@ -94,7 +95,7 @@ namespace CloudGaming.Code.Cache.Special var serializedGameInfos = tempDataList .Select(info => new HashEntry($"gameInfo:{info.GameId}", JsonConvert.SerializeObject(info))) .ToArray(); - database.HashSet(key, serializedGameInfos); + database.HashSet(RedisKey, serializedGameInfos); MemoryCacheHelper.SetCache(key, tempDataList, 60 * 60); _dataList = tempDataList; diff --git a/src/CloudGaming/Code/CloudGaming.Code/DataAccess/MultiTenantUtil/MultiTenantTenantMiddleware.cs b/src/CloudGaming/Code/CloudGaming.Code/DataAccess/MultiTenantUtil/MultiTenantTenantMiddleware.cs index 40c30bd..1174cf9 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/DataAccess/MultiTenantUtil/MultiTenantTenantMiddleware.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/DataAccess/MultiTenantUtil/MultiTenantTenantMiddleware.cs @@ -29,8 +29,7 @@ namespace CloudGaming.Code.DataAccess.MultiTenantUtil /// public virtual async Task Invoke(HttpContext context, IServiceProvider _serviceProvider, - AppConfig appConfig - ) + AppConfig appConfig ) { var host = context.Request.Host.Host; diff --git a/src/CloudGaming/Code/CloudGaming.Code/Epg/EpgExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/Epg/EpgExtend.cs index 4f7f399..b0f5875 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Epg/EpgExtend.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Epg/EpgExtend.cs @@ -47,8 +47,14 @@ namespace CloudGaming.Code.Epg return null; } - epgInfo.Title ??= gameInfo.GameName; - epgInfo.SubTitle ??= gameInfo.Title2; + if (string.IsNullOrEmpty(epgInfo.Title)) + { + epgInfo.Title = gameInfo.GameName; + } + if (string.IsNullOrEmpty(epgInfo.SubTitle)) + { + epgInfo.SubTitle = gameInfo.Title2; + } if (epgInfo.ImageUrl == 0 && !string.IsNullOrEmpty(epgCfg.ImageResStyle)) { diff --git a/src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs new file mode 100644 index 0000000..b032836 --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs @@ -0,0 +1,64 @@ +using CloudGaming.Code.Cache; +using CloudGaming.DtoModel.Game; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.Game +{ + /// + /// 游戏逻辑类 + /// + public class GameBLL : CloudGamingBase + { + public GameBLL(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + + /// + /// + /// + /// + public async Task> GetGameTypeListAsync() + { + var gameList = Cache.GameEntityCache?.DataList ?? new List(); + var gameTypes = await Task.Run(() => + { + return CloudGamingCacheExtend.GetDataEntityCache(this, it => it.IsOnline)?.DataList + .Where(it => gameList.Any(item => item.GameType?.Any(gameType => gameType.Id == it.TypeId) ?? false)) + .OrderBy(it => it.OrderId) + .Select(it => new GameExtendedAttribute + { + Id = it.TypeId, + Name = it.TypeName, + OrderId = it.OrderId + }) + .ToList(); + }); + + return gameTypes; + } + + /// + /// 根据游戏类型Id 获取游戏列表 + /// + /// + /// + public async Task> GetGameListAsync(int typeId) + { + + var gameListDto = await Task.Run(() => + { + var gameList = Cache.GameEntityCache?.DataList ?? new List(); + var x = gameList.Where(it => it.GameType?.Any(item => item.Id == typeId) ?? false).Select(it => new + GameListDto(it)).ToList(); + return x; + }); + return gameListDto; + + } + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MemoryCacheMiddleware.cs b/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MemoryCacheMiddleware.cs new file mode 100644 index 0000000..0cd044c --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MemoryCacheMiddleware.cs @@ -0,0 +1,147 @@ +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.IdentityModel.Tokens; +using System.Collections.Concurrent; + +namespace CloudGaming.Code.MiddlewareExtend +{ + /// + /// 内存缓存 + /// + public class MemoryCacheMiddleware + { + private readonly RequestDelegate _next; + private readonly IMemoryCache _cache; + private static readonly ConcurrentDictionary _attributeCache = new(); + /// + /// + /// + /// + /// + public MemoryCacheMiddleware(RequestDelegate next, IMemoryCache cache) + { + _next = next; + _cache = cache; + } + + public async Task InvokeAsync(HttpContext context, + IServiceProvider _serviceProvider, + AppConfig appConfig + ) + { + // 检查当前请求是否需要缓存 + var cacheAttribute = GetCacheAttribute(context); + if (cacheAttribute == null) + { + // 如果没有找到 MemoryCacheAttribute,直接调用下一个中间件 + await _next(context); + return; + } + + // 生成缓存键(基于请求路径和查询字符串) + var cacheKey = GenerateCacheKey(context.Request, appConfig); + + // 尝试从缓存中获取数据 + if (_cache.TryGetValue(cacheKey, out string cachedResponse)) + { + context.Response.StatusCode = StatusCodes.Status200OK; + // 如果缓存中有数据,则直接返回缓存的响应 + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(cachedResponse); + return; + } + + // 捕获原始响应流 + var originalResponseStream = context.Response.Body; + + try + { + using (var memoryStream = new MemoryStream()) + { + context.Response.Body = memoryStream; + + // 调用下一个中间件 + await _next(context); + + // 将响应流重新定位到起始位置 + memoryStream.Position = 0; + + // 读取响应内容 + var responseBody = await new StreamReader(memoryStream).ReadToEndAsync(); + + // 将响应内容缓存 + _cache.Set(cacheKey, responseBody, cacheAttribute.TimeSpan); + + // 将内容写回原始响应流 + memoryStream.Position = 0; + await memoryStream.CopyToAsync(originalResponseStream); + } + } + finally + { + // 恢复原始响应流 + context.Response.Body = originalResponseStream; + } + } + + private MemoryCacheAttribute GetCacheAttribute(HttpContext context) + { + var endpoint = context.Features.Get()?.Endpoint; + if (endpoint == null) return null; + + // 使用字典缓存以减少重复获取 + if (_attributeCache.TryGetValue(endpoint, out var cachedAttribute)) + { + return cachedAttribute; + } + + // 获取并缓存 MemoryCacheAttribute + var attribute = endpoint.Metadata.GetMetadata(); + if (attribute != null) + { + _attributeCache.TryAdd(endpoint, attribute); + } + + return attribute; + } + + private string GenerateCacheKey(HttpRequest request, AppConfig appConfig) + { + var appRequestInfo = new AppRequestConfig(request); + // 基于请求路径和查询参数生成缓存键 + var cacheKey = $"{appConfig.Identifier}:{request.Path.Value.Replace('/', '.').TrimStart('.')}:{(string.IsNullOrEmpty(request.QueryString.Value) ? "default" : request.QueryString)}:{appRequestInfo.Key}"; + return cacheKey; + } + } + /// + /// 内存缓存特性类 + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class MemoryCacheAttribute : Attribute + { + + public TimeSpan TimeSpan { get; } + public MemoryCacheAttribute(int durationInSeconds) + { + TimeSpan = TimeSpan.FromSeconds(durationInSeconds); + } + public MemoryCacheAttribute(int hours, int minutes, int seconds) + { + + TimeSpan = new TimeSpan(hours, minutes, seconds); + } + public MemoryCacheAttribute(int minutes, int seconds) + { + + TimeSpan = new TimeSpan(0, minutes, seconds); + } + } + +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MiddlewareExtends.cs b/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MiddlewareExtends.cs new file mode 100644 index 0000000..aa3a709 --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/MiddlewareExtends.cs @@ -0,0 +1,45 @@ +using HuanMeng.DotNetCore.MiddlewareExtend; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.MiddlewareExtend +{ + /// + /// + /// + public static class MiddlewareExtends + { + /// + /// 加载全部中间件 + /// + /// + /// + public static IApplicationBuilder UseCloudGamingMiddlewareAll(this IApplicationBuilder builder) + { + return builder + .UseCacheMiddleware() + .UseRedisCacheMiddleware() + ; + + } + + /// + /// 缓存中间件 + /// + /// + /// + public static IApplicationBuilder UseCacheMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + public static IApplicationBuilder UseRedisCacheMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/RedisCacheMiddleware.cs b/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/RedisCacheMiddleware.cs new file mode 100644 index 0000000..fb1080d --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/MiddlewareExtend/RedisCacheMiddleware.cs @@ -0,0 +1,124 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.Caching.Distributed; + +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.MiddlewareExtend +{ + /// + /// Redis 缓存中间件 + /// + public class RedisCacheMiddleware + { + private readonly RequestDelegate _next; + + private static readonly ConcurrentDictionary _attributeCache = new(); + + public RedisCacheMiddleware(RequestDelegate next) + { + _next = next; + + } + + public async Task InvokeAsync(HttpContext context, + IServiceProvider _serviceProvider, + AppConfig appConfig + ) + { + // 检查当前请求是否需要缓存 + var cacheAttribute = GetCacheAttribute(context); + if (cacheAttribute == null) + { + await _next(context); + return; + } + var _cache = appConfig.GetRedisDataBase(); + + // 生成缓存键(基于请求路径和查询字符串) + var cacheKey = GenerateCacheKey(context.Request, appConfig); + + // 尝试从 Redis 缓存中获取数据 + var cachedResponse = await _cache.StringGetAsync(cacheKey); + if (!cachedResponse.IsNullOrEmpty) + { + context.Response.StatusCode = StatusCodes.Status200OK; + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(cachedResponse); + return; + } + + // 捕获原始响应流 + var originalResponseStream = context.Response.Body; + + try + { + using (var memoryStream = new MemoryStream()) + { + context.Response.Body = memoryStream; + + // 调用下一个中间件 + await _next(context); + + // 将响应流重新定位到起始位置 + memoryStream.Position = 0; + + // 读取响应内容 + var responseBody = await new StreamReader(memoryStream).ReadToEndAsync(); + + await _cache.StringSetAsync(cacheKey, responseBody, cacheAttribute.TimeSpan); + + // 将内容写回原始响应流 + memoryStream.Position = 0; + await memoryStream.CopyToAsync(originalResponseStream); + } + } + finally + { + context.Response.Body = originalResponseStream; + } + } + + private RedisCacheAttribute GetCacheAttribute(HttpContext context) + { + var endpoint = context.Features.Get()?.Endpoint; + if (endpoint == null) return null; + + if (_attributeCache.TryGetValue(endpoint, out var cachedAttribute)) + { + return cachedAttribute; + } + + var attribute = endpoint.Metadata.GetMetadata(); + if (attribute != null) + { + _attributeCache.TryAdd(endpoint, attribute); + } + + return attribute; + } + + private string GenerateCacheKey(HttpRequest request, AppConfig appConfig) + { + var appRequestInfo = new AppRequestConfig(request); + var cacheKey = $"cache:api:{request.Path.Value.Replace('/', '.').TrimStart('.')}:{appRequestInfo.Key}:{(string.IsNullOrEmpty(request.QueryString.Value) ? "default" : request.QueryString)}"; + return cacheKey; + } + } + + /// + /// Redis 缓存特性类 + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class RedisCacheAttribute : Attribute + { + public TimeSpan TimeSpan { get; } + public RedisCacheAttribute(int durationInSeconds) => TimeSpan = TimeSpan.FromSeconds(durationInSeconds); + public RedisCacheAttribute(int hours, int minutes, int seconds) => TimeSpan = new TimeSpan(hours, minutes, seconds); + public RedisCacheAttribute(int minutes, int seconds) => TimeSpan = new TimeSpan(0, minutes, seconds); + } +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameInfoDto.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameInfoDto.cs new file mode 100644 index 0000000..524b1de --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameInfoDto.cs @@ -0,0 +1,40 @@ +using HuanMeng.DotNetCore.AttributeExtend; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.Game +{ + public class GameInfoDto + { + /// + /// 游戏Id + /// + public virtual string GameId { get; set; } = null!; + + + /// + /// 游戏icon + /// + [Images("ImageIcon")] + public virtual int ImageIcon { get; set; } + + /// + /// + /// + [Images("GameBgImage")] + public virtual int GameBgImage { get; set; } + /// + /// 游戏标签 + /// + public List GameTags { get; set; } + + /// + /// 游戏列表 + /// + public List GameType { get; set; } + } +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs new file mode 100644 index 0000000..d58e359 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs @@ -0,0 +1,48 @@ +using HuanMeng.DotNetCore.AttributeExtend; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.Game +{ + /// + /// 游戏列表数据 + /// + public class GameListDto + { + public GameListDto() { } + + /// + /// + /// + /// + public GameListDto(GameInfo gameInfo) + { + if (gameInfo != null) + { + this.GameName = gameInfo.GameName; + this.GameId = gameInfo.GameId; + this.GameIconImage = gameInfo.GameImageId; + + + } + } + /// + /// 游戏Id + /// + public string GameId { get; set; } + /// + /// 游戏名称 + /// + public string GameName { get; set; } + + /// + /// 游戏icon + /// + [Images] + public int GameIconImage { get; set; } + } +} diff --git a/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions1.cs b/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions1.cs index acce3cf..636d4cc 100644 --- a/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions1.cs +++ b/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions1.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Reflection; using HuanMeng.DotNetCore.AttributeExtend; using System.Linq.Expressions; +using Microsoft.IdentityModel.Tokens; namespace HuanMeng.DotNetCore.Utility; @@ -23,7 +24,7 @@ public static class ObjectExtensions /// /// 缓存每个属性是否具有 ImagesAttribute 特性。 /// - public static readonly ConcurrentDictionary _PropertyCache = new(); + public static readonly ConcurrentDictionary _PropertyCache = new(); /// /// 判断对象是否为原始类型或字符串类型。 @@ -102,8 +103,8 @@ public static class ObjectExtensions // 如果属性是字符串,在其值前添加 "test" if (propertyValue is string stringValue) { - keyValuePairs[accessor.PropertyName] = $"test{stringValue}"; - Console.WriteLine(propertyPath); + keyValuePairs[accessor.PropertyName] = stringValue; + //Console.WriteLine(propertyPath); continue; } @@ -130,8 +131,16 @@ public static class ObjectExtensions // 创建用于访问属性值的委托 var getter = CreatePropertyGetter(type, property); // 检查属性是否具有 ImagesAttribute,并将结果存储在缓存中 - bool hasImagesAttribute = _PropertyCache.GetOrAdd(property, p => p.GetCustomAttribute() != null); - return new PropertyAccessor(property.Name, getter, hasImagesAttribute); + var imagesAttribute = _PropertyCache.GetOrAdd(property, p => p.GetCustomAttribute()); + if (imagesAttribute != null) + { + if (!string.IsNullOrEmpty(imagesAttribute.FieldName)) + { + return new PropertyAccessor(imagesAttribute.FieldName, getter, true); + } + return new PropertyAccessor(property.Name, getter, true); + } + return new PropertyAccessor(property.Name, getter, false); }).ToArray(); }