diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppLanguage.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppLanguage.cs new file mode 100644 index 0000000..c55ee0b --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppLanguage.cs @@ -0,0 +1,116 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.AppExtend; +/// +/// app多语言 +/// +public static class AppLanguage +{ + /// + /// 多语言管理 + /// + public static ConcurrentDictionary>>> AppConfigLanguages { get; set; } = new ConcurrentDictionary>>>(); + + /// + /// 获取当前项目的多语言配置 + /// + /// + /// + public static ConcurrentDictionary>> GetAppConfigLanguage(this AppConfig appConfig) + { + if (!AppConfigLanguages.TryGetValue(appConfig.Identifier, out var language)) + { + language = new ConcurrentDictionary>>(); + AppConfigLanguages.TryAdd(appConfig.Identifier, language); + } + return language; + } + + /// + /// 获取当前接口的多语言配置 + /// + /// + /// api地址 + /// + public static ConcurrentDictionary> GetAppLanguage(this AppConfig appConfig, string language) + { + var dic = GetAppConfigLanguage(appConfig); + + if (!dic.TryGetValue(language, out var languageDic)) + { + languageDic = new ConcurrentDictionary>(); + dic.TryAdd(language, languageDic); + } + + return languageDic; + } + + /// + /// 获取当前接口的多语言配置 + /// + /// + /// api地址 + /// + public static ConcurrentDictionary GetAppApiLanguage(this AppConfig appConfig, string language, string api) + { + var dic = GetAppLanguage(appConfig, language); + + if (!dic.TryGetValue(api, out var languageDic)) + { + languageDic = new ConcurrentDictionary(); + dic.TryAdd(api, languageDic); + } + + return languageDic; + } + + /// + /// 加载多语言配置 + /// + /// + /// + public static void InitAppLanguage(this AppConfig appConfig, string _language, string json) + { + if (AppConfigLanguages == null) + { + AppConfigLanguages = new ConcurrentDictionary>>>(); + } + //获取当前项目的多语言配置 + var appLanguage = AppConfigLanguages.GetOrAdd(appConfig.Identifier, (t) => new ConcurrentDictionary>>()); + //初始化json数据 + var cacheLanguage = JsonConvert.DeserializeObject>>(json); + //重新定义当前项目的多语言 + var innerDict = new ConcurrentDictionary>(); + foreach (var item in cacheLanguage) + { + + var t = new ConcurrentDictionary(item.Value); + innerDict.TryAdd(item.Key, t); + } + appLanguage.AddOrUpdate(_language, (t) => innerDict, (t, o) => innerDict); + } + + /// + /// 保存多语言配置 + /// + /// + /// + public static string LanguageToJson(AppConfig appConfig) + { + var settings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; + var appLanguage = GetAppConfigLanguage(appConfig); + var json = JsonConvert.SerializeObject(appLanguage, settings); + return json; + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppService.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppService.cs index 3b084fc..d462e33 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppService.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppService.cs @@ -28,6 +28,9 @@ public class AppService(IServiceProvider scopeFactory) : IHostedService CloudGamingBase cloudGamingBase = new CloudGamingBase(scopedProvider); //加载图片缓存 cloudGamingBase.Cache.AppImageCache.ReloadData(); + //cloudGamingBase.RedisCache.StringGet("language"); + //appConfig.InitAppLanguage(); + } return Task.CompletedTask; } diff --git a/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs b/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs index aa61198..43b2689 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs @@ -88,15 +88,22 @@ public class CustomResultFilter : IResultFilter } } } - var dic = value.ToDictionaryOrList(apiPrefix, it => cloudGamingBase.Cache.AppImageCache[it]); + var language = _appConfig.GetAppLanguage(apiPrefix); + var dic = value.ToDictionaryOrList(false, apiPrefix, it => cloudGamingBase.Cache.AppImageCache[it], (value, prefix, isArray) => + { + if (value.ContainsChineseOptimized()) + { + //中文 + var v = language.GetOrAdd(value, value); + if (!string.IsNullOrEmpty(v)) + { + return v; + } + } + return value; + }); objectResult.Value = dic; } - //else - //{ - // //value = objectResult.Value; - //} - - sw.Stop(); context.HttpContext.Response.Headers.TryAdd("X-Request-Duration-Filter", sw.Elapsed.TotalMilliseconds.ToString()); } diff --git a/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions.cs b/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions.cs index 83b139f..9b6a7c9 100644 --- a/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions.cs +++ b/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions.cs @@ -44,15 +44,15 @@ public static class ObjectExtensions /// 要转换的对象。 /// 属性路径的可选前缀。 /// 对象的字典或列表表示形式。 - public static object ToDictionaryOrList(this object obj, string prefix = "", Func? imageFunc = null) + public static object ToDictionaryOrList(this object obj, bool isEnumerable, string prefix = "", Func? imageFunc = null, Func? languageFunc = null) { if (obj == null) return null; return obj switch { _ when IsPrimitiveType(obj) => obj, - IEnumerable enumerable => TransformCollection(enumerable, prefix, imageFunc), - _ => TransformObject(obj, prefix, imageFunc) + IEnumerable enumerable => TransformCollection(enumerable, prefix, imageFunc, languageFunc), + _ => TransformObject(obj, isEnumerable, prefix, imageFunc, languageFunc) }; } @@ -62,13 +62,13 @@ public static class ObjectExtensions /// 要转换的集合。 /// 集合中每个属性路径的前缀。 /// 转换后的项列表。 - private static List TransformCollection(IEnumerable enumerable, string prefix = "", Func? imageFunc = null) + private static List TransformCollection(IEnumerable enumerable, string prefix = "", Func? imageFunc = null, Func? languageFunc = null) { var list = new List(enumerable is ICollection collection ? collection.Count : 10); int index = 0; foreach (var item in enumerable) { - list.Add(ToDictionaryOrList(item, $"{prefix}.[{index}]", imageFunc)); // 为集合中每个项添加路径 + list.Add(ToDictionaryOrList(item, true, $"{prefix}.[{index}]", imageFunc, languageFunc)); // 为集合中每个项添加路径 index++; } return list; @@ -80,7 +80,7 @@ public static class ObjectExtensions /// 要转换的对象。 /// 每个属性路径的前缀。 /// 包含属性名和属性值的字典。 - private static Dictionary TransformObject(object obj, string prefix = "", Func? imageFunc = null) + private static Dictionary TransformObject(object obj, bool isEnumerable, string prefix = "", Func? imageFunc = null, Func? languageFunc = null) { if (obj == null) { @@ -100,8 +100,16 @@ public static class ObjectExtensions // 如果属性是字符串,在其值前添加 "test" if (propertyValue is string stringValue) { + if (stringValue == null) + { + keyValuePairs[accessor.PropertyName] = ""; + continue; + } + if (!string.IsNullOrEmpty(stringValue) && languageFunc != null) + { + stringValue = languageFunc?.Invoke(stringValue, propertyPath, false) ?? ""; + } keyValuePairs[accessor.PropertyName] = stringValue; - //Console.WriteLine(propertyPath); continue; } @@ -109,7 +117,7 @@ public static class ObjectExtensions // 否则,如果是集合类型,则递归转换 keyValuePairs[accessor.PropertyName] = accessor.HasImagesAttribute ? imageFunc?.Invoke((int)propertyValue) ?? "" - : ToDictionaryOrList(propertyValue, propertyPath, imageFunc); // IsCollectionType(propertyValue) ?: propertyValue; + : ToDictionaryOrList(propertyValue, isEnumerable, propertyPath, imageFunc, languageFunc); // IsCollectionType(propertyValue) ?: propertyValue; } return keyValuePairs; diff --git a/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions1.cs b/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions1.cs deleted file mode 100644 index 1bc2acf..0000000 --- a/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/ObjectExtensions1.cs +++ /dev/null @@ -1,585 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using HuanMeng.DotNetCore.AttributeExtend; -using System.Linq.Expressions; -using Microsoft.IdentityModel.Tokens; - - -namespace HuanMeng.DotNetCore.Utility; - - -[Obsolete] -public static class ObjectExtensions11 -{ - /// - /// 缓存属性信息以提高反射访问的性能,使用 ConcurrentDictionary 确保线程安全 - /// - private static readonly ConcurrentDictionary PropertyCache = new(); - - /// - /// 判断对象是否为基础类型。 - /// - public static bool IsPrimitiveType(object obj) => - obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType); - - /// - /// 判断对象是否为集合类型(排除字符串)。 - /// - public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string; - - /// - /// 判断对象是否为复杂类型。 - /// - public static bool IsComplexType(object obj) => - obj is not null && !IsPrimitiveType(obj) && !IsCollectionType(obj); - - /// - /// 转换对象为字典或列表 - /// - public static object ToDictionaryOrList(object obj) - { - if (obj == null) return null; - - return obj switch - { - // 基础类型 - _ when IsPrimitiveType(obj) => obj, - // 集合类型 - IEnumerable enumerable => TransformCollection(enumerable), - // 复杂类型 - _ => TransformObject(obj) - }; - } - - /// - /// 转换集合为列表 - /// - private static List TransformCollection(IEnumerable enumerable) - { - var list = new List(); - foreach (var item in enumerable) - { - list.Add(item.ToDictionaryOrList()); - } - return list; - } - - /// - /// 转换对象为字典 - /// - private static Dictionary TransformObject(object obj) - { - var type = obj.GetType(); - var properties = PropertyCache.GetOrAdd(type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance)); - var keyValuePairs = new Dictionary(); - - foreach (var property in properties) - { - var propertyValue = property.GetValue(obj); - keyValuePairs[property.Name] = IsCollectionType(propertyValue) - ? propertyValue.ToDictionaryOrList() - : propertyValue; - } - - return keyValuePairs; - } -} - -[Obsolete] -public static class ObjectExtensions1 -{ - private static readonly ConcurrentDictionary PropertyCache = new(); - private static readonly ConcurrentDictionary HasImagesAttributeCache = new(); - - public static bool IsPrimitiveType(object obj) => - obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType); - - public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string; - - public static bool IsComplexType(object obj) => - obj is not null && !IsPrimitiveType(obj) && !IsCollectionType(obj); - - public static object ToDictionaryOrList(object obj) - { - if (obj == null) return null; - - return obj switch - { - _ when IsPrimitiveType(obj) => obj, - IEnumerable enumerable => TransformCollection(enumerable), - _ => TransformObject(obj) - }; - } - - private static List TransformCollection(IEnumerable enumerable) - { - var list = new List(enumerable is ICollection collection ? collection.Count : 10); - foreach (var item in enumerable) - { - list.Add(ToDictionaryOrList(item)); - } - return list; - } - - private static Dictionary TransformObject(object obj) - { - var type = obj.GetType(); - var properties = PropertyCache.GetOrAdd(type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance)); - var keyValuePairs = new Dictionary(properties.Length); - - foreach (var property in properties) - { - // 预先缓存 ImagesAttribute 判断结果 - if (!HasImagesAttributeCache.TryGetValue(property, out bool hasImagesAttribute)) - { - hasImagesAttribute = property.GetCustomAttribute() != null; - HasImagesAttributeCache.TryAdd(property, hasImagesAttribute); - } - var propertyValue = property.GetValue(obj); - if (hasImagesAttribute) - { - keyValuePairs[property.Name] = $"image{propertyValue}"; - continue; - } - - keyValuePairs[property.Name] = IsCollectionType(propertyValue) - ? ToDictionaryOrList(propertyValue) - : propertyValue; - if (propertyValue is IEnumerable imagesEnumerable) - { - keyValuePairs[property.Name] = TransformCollection(imagesEnumerable); - } - } - - return keyValuePairs; - } -} -[Obsolete] -public static class ObjectExtensions3 -{ - private static readonly ConcurrentDictionary PropertyAccessorsCache = new(); - private static readonly ConcurrentDictionary HasImagesAttributeCache = new(); - public static bool IsPrimitiveType(object obj) => - obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType); - - public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string; - - public static object ToDictionaryOrList(object obj) - { - if (obj == null) return null; - - return obj switch - { - _ when IsPrimitiveType(obj) => obj, - IEnumerable enumerable => TransformCollection(enumerable), - _ => TransformObject(obj) - }; - } - - private static List TransformCollection(IEnumerable enumerable) - { - var list = new List(); - foreach (var item in enumerable) - { - list.Add(ToDictionaryOrList(item)); - } - return list; - } - - private static Dictionary TransformObject(object obj) - { - var type = obj.GetType(); - var accessors = PropertyAccessorsCache.GetOrAdd(type, CreatePropertyAccessors); - var keyValuePairs = new Dictionary(accessors.Length); - - foreach (var accessor in accessors) - { - var propertyValue = accessor.Getter(obj); - keyValuePairs[accessor.Name] = IsCollectionType(propertyValue) - ? ToDictionaryOrList(propertyValue) - : propertyValue; - } - - return keyValuePairs; - } - - private static PropertyAccessor[] CreatePropertyAccessors(Type type) - { - var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); - var accessors = new PropertyAccessor[properties.Length]; - - for (int i = 0; i < properties.Length; i++) - { - var property = properties[i]; - //var x = property.GetCustomAttribute() != null; - - var getter = CreateGetter(property); - accessors[i] = new PropertyAccessor(property.Name, getter); - } - - return accessors; - } - - private static Func CreateGetter(PropertyInfo property) - { - var parameter = Expression.Parameter(typeof(object), "instance"); - var castInstance = Expression.Convert(parameter, property.DeclaringType); - var propertyAccess = Expression.Property(castInstance, property); - var castResult = Expression.Convert(propertyAccess, typeof(object)); - var lambda = Expression.Lambda>(castResult, parameter); - return lambda.Compile(); - } - - private record PropertyAccessor(string Name, Func Getter); -} - -[Obsolete] -public static class ObjectExtensions5 -{ - // 用于缓存每个类型的属性访问器数组,以减少重复的反射操作 - private static readonly ConcurrentDictionary PropertyCache = new(); - - // 判断对象是否为原始类型、字符串或值类型 - public static bool IsPrimitiveType(object obj) => - obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType); - - // 判断对象是否为集合类型(非字符串的 IEnumerable) - public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string; - - /// - /// 将对象转换为字典或列表结构 - /// - /// - /// - public static object ToDictionaryOrList(object obj) - { - if (obj == null) return null; - - // 根据对象类型执行相应的转换操作 - return obj switch - { - _ when IsPrimitiveType(obj) => obj, // 原始类型直接返回 - IEnumerable enumerable => TransformCollection(enumerable), // 集合类型转换为列表 - _ => TransformObject(obj) // 复杂类型转换为字典 - }; - } - - /// - /// 转换集合类型,将每个元素递归转换为字典或列表 - /// - /// - /// - private static List TransformCollection(IEnumerable enumerable) - { - var list = new List(enumerable is ICollection collection ? collection.Count : 10); - foreach (var item in enumerable) - { - list.Add(ToDictionaryOrList(item)); - } - return list; - } - - // 转换复杂类型为字典结构,键为属性名,值为属性值 - private static Dictionary TransformObject(object obj) - { - var type = obj.GetType(); - - // 从缓存中获取或创建该类型的属性访问器数组 - var accessors = PropertyCache.GetOrAdd(type, t => CreatePropertyAccessors(t)); - var keyValuePairs = new Dictionary(accessors.Length); - - // 遍历每个属性访问器 - foreach (var accessor in accessors) - { - // 使用表达式树生成的委托获取属性值 - var propertyValue = accessor.Getter(obj); - - // 如果属性具有 ImagesAttribute 特性,将其值转换为 "image{propertyValue}" 格式 - if (accessor.HasImagesAttribute) - { - keyValuePairs[accessor.PropertyName] = $"image{propertyValue}"; - } - else - { - // 根据属性值的类型决定是否递归转换 - keyValuePairs[accessor.PropertyName] = IsCollectionType(propertyValue) - ? ToDictionaryOrList(propertyValue) - : propertyValue; - } - } - - return keyValuePairs; - } - - // 创建指定类型的属性访问器数组 - private static PropertyAccessor[] CreatePropertyAccessors(Type type) - { - // 获取类型的公共实例属性 - var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); - var accessors = new List(properties.Length); - - foreach (var property in properties) - { - // 使用表达式树生成委托来获取属性值,避免使用反射 - var parameter = Expression.Parameter(typeof(object), "obj"); // 输入参数 obj - var castParameter = Expression.Convert(parameter, type); // 将参数转换为目标类型 - var propertyAccess = Expression.Property(castParameter, property); // 获取属性值 - var convertPropertyAccess = Expression.Convert(propertyAccess, typeof(object)); // 转换为 object 类型 - var getter = Expression.Lambda>(convertPropertyAccess, parameter).Compile(); - - // 检查属性是否具有 ImagesAttribute 特性 - bool hasImagesAttribute = property.GetCustomAttribute() != null; - - // 将属性名、Getter 委托和特性标识添加到 PropertyAccessor 对象中 - accessors.Add(new PropertyAccessor(property.Name, getter, hasImagesAttribute)); - } - - return accessors.ToArray(); - } - - // 表示属性访问器的类,包含属性名称、Getter 委托和特性标识 - private class PropertyAccessor - { - public string PropertyName { get; } // 属性名称 - public Func Getter { get; } // 委托,用于获取属性值 - public bool HasImagesAttribute { get; } // 是否包含 ImagesAttribute 特性 - - public PropertyAccessor(string propertyName, Func getter, bool hasImagesAttribute) - { - PropertyName = propertyName; - Getter = getter; - HasImagesAttribute = hasImagesAttribute; - } - } -} - -[Obsolete] -public static class ObjectExtensions6 -{ - /// - /// 使用线程安全的字典缓存每个类型的属性访问器 - /// - private static readonly ConcurrentDictionary PropertyCache = new(); - /// - /// 缓存每个属性是否具有 ImagesAttribute 特性 - /// - private static readonly ConcurrentDictionary _PropertyCache = new ConcurrentDictionary(); - - /// - /// 判断对象是否为原始类型或字符串 - /// - /// - /// - public static bool IsPrimitiveType(object obj) => - obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType); - - /// - /// 判断对象是否为集合类型(但不是字符串) - /// - /// - /// - public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string; - - /// - /// 将对象转换为字典或列表 - /// - /// - /// - public static object ToDictionaryOrList(object obj) - { - if (obj == null) return null; - - return obj switch - { - _ when IsPrimitiveType(obj) => obj, - IEnumerable enumerable => TransformCollection(enumerable), - _ => TransformObject(obj) - }; - } - - /// - /// 将集合转换为列表 - /// - /// - /// - private static List TransformCollection(IEnumerable enumerable) - { - // 如果集合实现了 ICollection 接口,则使用其 Count 属性初始化列表容量 - var list = new List(enumerable is ICollection collection ? collection.Count : 10); - foreach (var item in enumerable) - { - list.Add(ToDictionaryOrList(item)); - } - return list; - } - - // 将对象转换为字典 - private static Dictionary TransformObject(object obj) - { - var type = obj.GetType(); - // 获取或创建该类型的属性访问器 - var accessors = PropertyCache.GetOrAdd(type, t => CreatePropertyAccessors(t)); - var keyValuePairs = new Dictionary(accessors.Length); - - foreach (var accessor in accessors) - { - var propertyValue = accessor.Getter(obj); - - if (accessor.HasImagesAttribute) - { - // 如果属性具有 ImagesAttribute 特性,处理方式不同 - keyValuePairs[accessor.PropertyName] = $"image{propertyValue}"; - } - else - { - // 如果属性是集合类型,递归转换 - keyValuePairs[accessor.PropertyName] = IsCollectionType(propertyValue) - ? ToDictionaryOrList(propertyValue) - : propertyValue; - } - } - - return keyValuePairs; - } - - // 创建属性访问器数组 - private static PropertyAccessor[] CreatePropertyAccessors(Type type) - { - var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); - var accessors = new List(properties.Length); - - foreach (var property in properties) - { - var parameter = Expression.Parameter(typeof(object), "obj"); - var castParameter = Expression.Convert(parameter, type); - var propertyAccess = Expression.Property(castParameter, property); - var convertPropertyAccess = Expression.Convert(propertyAccess, typeof(object)); - var getter = Expression.Lambda>(convertPropertyAccess, parameter).Compile(); - - // 使用缓存检查属性是否具有 ImagesAttribute 特性 - bool hasImagesAttribute = GetHasImagesAttribute(property, _PropertyCache); - - accessors.Add(new PropertyAccessor(property.Name, getter, hasImagesAttribute)); - } - - return accessors.ToArray(); - } - - // 检查属性是否具有 ImagesAttribute 特性,并缓存结果 - private static bool GetHasImagesAttribute(PropertyInfo property, ConcurrentDictionary propertyCache) - { - if (propertyCache.TryGetValue(property, out bool hasImagesAttribute)) - { - return hasImagesAttribute; - } - - hasImagesAttribute = property.GetCustomAttribute() != null; - propertyCache[property] = hasImagesAttribute; - - return hasImagesAttribute; - } - - // 属性访问器类,包含属性名、获取器和特性标志 - private class PropertyAccessor - { - public string PropertyName { get; } - public Func Getter { get; } - public bool HasImagesAttribute { get; } - - public PropertyAccessor(string propertyName, Func getter, bool hasImagesAttribute) - { - PropertyName = propertyName; - Getter = getter; - HasImagesAttribute = hasImagesAttribute; - } - } -} - -[Obsolete] -public static class ObjectExtensions7 -{ - private static readonly ConcurrentDictionary PropertyCache = new(); - private static readonly ConcurrentDictionary _PropertyCache = new(); - - public static bool IsPrimitiveType(object obj) => - obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType); - - public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string; - - public static object ToDictionaryOrList(object obj) - { - if (obj == null) return null; - - return obj switch - { - _ when IsPrimitiveType(obj) => obj, - IEnumerable enumerable => TransformCollection(enumerable), - _ => TransformObject(obj) - }; - } - - private static List TransformCollection(IEnumerable enumerable) - { - var list = new List(enumerable is ICollection collection ? collection.Count : 10); - foreach (var item in enumerable) - { - list.Add(ToDictionaryOrList(item)); - } - return list; - } - - private static Dictionary TransformObject(object obj) - { - var type = obj.GetType(); - var accessors = PropertyCache.GetOrAdd(type, CreatePropertyAccessors); - var keyValuePairs = new Dictionary(accessors.Length); - - foreach (var accessor in accessors) - { - var propertyValue = accessor.Getter(obj); - keyValuePairs[accessor.PropertyName] = accessor.HasImagesAttribute - ? $"image{propertyValue}" - : IsCollectionType(propertyValue) ? ToDictionaryOrList(propertyValue) : propertyValue; - } - - return keyValuePairs; - } - - private static PropertyAccessor[] CreatePropertyAccessors(Type type) - { - var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); - return properties.Select(property => - { - var getter = CreatePropertyGetter(type, property); - bool hasImagesAttribute = _PropertyCache.GetOrAdd(property, p => p.GetCustomAttribute() != null); - return new PropertyAccessor(property.Name, getter, hasImagesAttribute); - }).ToArray(); - } - - private static Func CreatePropertyGetter(Type type, PropertyInfo property) - { - var parameter = Expression.Parameter(typeof(object), "obj"); - var castParameter = Expression.Convert(parameter, type); - var propertyAccess = Expression.Property(castParameter, property); - var convertPropertyAccess = Expression.Convert(propertyAccess, typeof(object)); - return Expression.Lambda>(convertPropertyAccess, parameter).Compile(); - } - - private class PropertyAccessor - { - public string PropertyName { get; } - public Func Getter { get; } - public bool HasImagesAttribute { get; } - - public PropertyAccessor(string propertyName, Func getter, bool hasImagesAttribute) - { - PropertyName = propertyName; - Getter = getter; - HasImagesAttribute = hasImagesAttribute; - } - } -} - diff --git a/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/StringExtend.cs b/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/StringExtend.cs new file mode 100644 index 0000000..14782ef --- /dev/null +++ b/src/CloudGaming/Utile/HuanMeng.DotNetCore/Utility/StringExtend.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.Utility; + +/// +/// 字符串扩展 +/// +public static class StringExtend +{ + /// + /// 判断字符串是否包含中文字符(使用字符遍历) + /// + /// 需要检查的字符串 + /// 如果包含中文字符,则返回 true;否则返回 false + public static bool ContainsChineseOptimized(this string input) + { + if (string.IsNullOrEmpty(input)) + { + return false; + } + + foreach (char c in input) + { + if (c >= '\u4e00' && c <= '\u9fa5') + { + return true; + } + } + return false; + } + +}