多语言v1

This commit is contained in:
zpc 2024-12-13 23:21:28 +08:00
parent 8caaffdb11
commit afae8967ee
6 changed files with 185 additions and 600 deletions

View File

@ -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;
/// <summary>
/// app多语言
/// </summary>
public static class AppLanguage
{
/// <summary>
/// 多语言管理
/// </summary>
public static ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, string>>>> AppConfigLanguages { get; set; } = new ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, string>>>>();
/// <summary>
/// 获取当前项目的多语言配置
/// </summary>
/// <param name="appConfig"></param>
/// <returns></returns>
public static ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, string>>> GetAppConfigLanguage(this AppConfig appConfig)
{
if (!AppConfigLanguages.TryGetValue(appConfig.Identifier, out var language))
{
language = new ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, string>>>();
AppConfigLanguages.TryAdd(appConfig.Identifier, language);
}
return language;
}
/// <summary>
/// 获取当前接口的多语言配置
/// </summary>
/// <param name="appConfig"></param>
/// <param name="language">api地址</param>
/// <returns></returns>
public static ConcurrentDictionary<string, ConcurrentDictionary<string, string>> GetAppLanguage(this AppConfig appConfig, string language)
{
var dic = GetAppConfigLanguage(appConfig);
if (!dic.TryGetValue(language, out var languageDic))
{
languageDic = new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>();
dic.TryAdd(language, languageDic);
}
return languageDic;
}
/// <summary>
/// 获取当前接口的多语言配置
/// </summary>
/// <param name="appConfig"></param>
/// <param name="language">api地址</param>
/// <returns></returns>
public static ConcurrentDictionary<string, string> GetAppApiLanguage(this AppConfig appConfig, string language, string api)
{
var dic = GetAppLanguage(appConfig, language);
if (!dic.TryGetValue(api, out var languageDic))
{
languageDic = new ConcurrentDictionary<string, string>();
dic.TryAdd(api, languageDic);
}
return languageDic;
}
/// <summary>
/// 加载多语言配置
/// </summary>
/// <param name="appConfig"></param>
/// <param name="json"></param>
public static void InitAppLanguage(this AppConfig appConfig, string _language, string json)
{
if (AppConfigLanguages == null)
{
AppConfigLanguages = new ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, string>>>>();
}
//获取当前项目的多语言配置
var appLanguage = AppConfigLanguages.GetOrAdd(appConfig.Identifier, (t) => new ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, string>>>());
//初始化json数据
var cacheLanguage = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json);
//重新定义当前项目的多语言
var innerDict = new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>();
foreach (var item in cacheLanguage)
{
var t = new ConcurrentDictionary<string, string>(item.Value);
innerDict.TryAdd(item.Key, t);
}
appLanguage.AddOrUpdate(_language, (t) => innerDict, (t, o) => innerDict);
}
/// <summary>
/// 保存多语言配置
/// </summary>
/// <param name="appConfig"></param>
/// <returns></returns>
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;
}
}

View File

@ -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;
}

View File

@ -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());
}

View File

@ -44,15 +44,15 @@ public static class ObjectExtensions
/// <param name="obj">要转换的对象。</param>
/// <param name="prefix">属性路径的可选前缀。</param>
/// <returns>对象的字典或列表表示形式。</returns>
public static object ToDictionaryOrList(this object obj, string prefix = "", Func<int, string>? imageFunc = null)
public static object ToDictionaryOrList(this object obj, bool isEnumerable, string prefix = "", Func<int, string>? imageFunc = null, Func<string, string, bool, string>? 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
/// <param name="enumerable">要转换的集合。</param>
/// <param name="prefix">集合中每个属性路径的前缀。</param>
/// <returns>转换后的项列表。</returns>
private static List<object> TransformCollection(IEnumerable enumerable, string prefix = "", Func<int, string>? imageFunc = null)
private static List<object> TransformCollection(IEnumerable enumerable, string prefix = "", Func<int, string>? imageFunc = null, Func<string, string, bool, string>? languageFunc = null)
{
var list = new List<object>(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
/// <param name="obj">要转换的对象。</param>
/// <param name="prefix">每个属性路径的前缀。</param>
/// <returns>包含属性名和属性值的字典。</returns>
private static Dictionary<string, object> TransformObject(object obj, string prefix = "", Func<int, string>? imageFunc = null)
private static Dictionary<string, object> TransformObject(object obj, bool isEnumerable, string prefix = "", Func<int, string>? imageFunc = null, Func<string, string, bool, string>? 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;

View File

@ -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
{
/// <summary>
/// 缓存属性信息以提高反射访问的性能,使用 ConcurrentDictionary 确保线程安全
/// </summary>
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropertyCache = new();
/// <summary>
/// 判断对象是否为基础类型。
/// </summary>
public static bool IsPrimitiveType(object obj) =>
obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);
/// <summary>
/// 判断对象是否为集合类型(排除字符串)。
/// </summary>
public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;
/// <summary>
/// 判断对象是否为复杂类型。
/// </summary>
public static bool IsComplexType(object obj) =>
obj is not null && !IsPrimitiveType(obj) && !IsCollectionType(obj);
/// <summary>
/// 转换对象为字典或列表
/// </summary>
public static object ToDictionaryOrList(object obj)
{
if (obj == null) return null;
return obj switch
{
// 基础类型
_ when IsPrimitiveType(obj) => obj,
// 集合类型
IEnumerable enumerable => TransformCollection(enumerable),
// 复杂类型
_ => TransformObject(obj)
};
}
/// <summary>
/// 转换集合为列表
/// </summary>
private static List<object> TransformCollection(IEnumerable enumerable)
{
var list = new List<object>();
foreach (var item in enumerable)
{
list.Add(item.ToDictionaryOrList());
}
return list;
}
/// <summary>
/// 转换对象为字典
/// </summary>
private static Dictionary<string, object> TransformObject(object obj)
{
var type = obj.GetType();
var properties = PropertyCache.GetOrAdd(type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance));
var keyValuePairs = new Dictionary<string, object>();
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<Type, PropertyInfo[]> PropertyCache = new();
private static readonly ConcurrentDictionary<PropertyInfo, bool> 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<object> TransformCollection(IEnumerable enumerable)
{
var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
foreach (var item in enumerable)
{
list.Add(ToDictionaryOrList(item));
}
return list;
}
private static Dictionary<string, object> TransformObject(object obj)
{
var type = obj.GetType();
var properties = PropertyCache.GetOrAdd(type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance));
var keyValuePairs = new Dictionary<string, object>(properties.Length);
foreach (var property in properties)
{
// 预先缓存 ImagesAttribute 判断结果
if (!HasImagesAttributeCache.TryGetValue(property, out bool hasImagesAttribute))
{
hasImagesAttribute = property.GetCustomAttribute<ImagesAttribute>() != 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<Type, PropertyAccessor[]> PropertyAccessorsCache = new();
private static readonly ConcurrentDictionary<PropertyInfo, bool> 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<object> TransformCollection(IEnumerable enumerable)
{
var list = new List<object>();
foreach (var item in enumerable)
{
list.Add(ToDictionaryOrList(item));
}
return list;
}
private static Dictionary<string, object> TransformObject(object obj)
{
var type = obj.GetType();
var accessors = PropertyAccessorsCache.GetOrAdd(type, CreatePropertyAccessors);
var keyValuePairs = new Dictionary<string, object>(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<ImagesAttribute>() != null;
var getter = CreateGetter(property);
accessors[i] = new PropertyAccessor(property.Name, getter);
}
return accessors;
}
private static Func<object, object> 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<Func<object, object>>(castResult, parameter);
return lambda.Compile();
}
private record PropertyAccessor(string Name, Func<object, object> Getter);
}
[Obsolete]
public static class ObjectExtensions5
{
// 用于缓存每个类型的属性访问器数组,以减少重复的反射操作
private static readonly ConcurrentDictionary<Type, PropertyAccessor[]> 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;
/// <summary>
/// 将对象转换为字典或列表结构
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static object ToDictionaryOrList(object obj)
{
if (obj == null) return null;
// 根据对象类型执行相应的转换操作
return obj switch
{
_ when IsPrimitiveType(obj) => obj, // 原始类型直接返回
IEnumerable enumerable => TransformCollection(enumerable), // 集合类型转换为列表
_ => TransformObject(obj) // 复杂类型转换为字典
};
}
/// <summary>
/// 转换集合类型,将每个元素递归转换为字典或列表
/// </summary>
/// <param name="enumerable"></param>
/// <returns></returns>
private static List<object> TransformCollection(IEnumerable enumerable)
{
var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
foreach (var item in enumerable)
{
list.Add(ToDictionaryOrList(item));
}
return list;
}
// 转换复杂类型为字典结构,键为属性名,值为属性值
private static Dictionary<string, object> TransformObject(object obj)
{
var type = obj.GetType();
// 从缓存中获取或创建该类型的属性访问器数组
var accessors = PropertyCache.GetOrAdd(type, t => CreatePropertyAccessors(t));
var keyValuePairs = new Dictionary<string, object>(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<PropertyAccessor>(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<Func<object, object>>(convertPropertyAccess, parameter).Compile();
// 检查属性是否具有 ImagesAttribute 特性
bool hasImagesAttribute = property.GetCustomAttribute<ImagesAttribute>() != null;
// 将属性名、Getter 委托和特性标识添加到 PropertyAccessor 对象中
accessors.Add(new PropertyAccessor(property.Name, getter, hasImagesAttribute));
}
return accessors.ToArray();
}
// 表示属性访问器的类包含属性名称、Getter 委托和特性标识
private class PropertyAccessor
{
public string PropertyName { get; } // 属性名称
public Func<object, object> Getter { get; } // 委托,用于获取属性值
public bool HasImagesAttribute { get; } // 是否包含 ImagesAttribute 特性
public PropertyAccessor(string propertyName, Func<object, object> getter, bool hasImagesAttribute)
{
PropertyName = propertyName;
Getter = getter;
HasImagesAttribute = hasImagesAttribute;
}
}
}
[Obsolete]
public static class ObjectExtensions6
{
/// <summary>
/// 使用线程安全的字典缓存每个类型的属性访问器
/// </summary>
private static readonly ConcurrentDictionary<Type, PropertyAccessor[]> PropertyCache = new();
/// <summary>
/// 缓存每个属性是否具有 ImagesAttribute 特性
/// </summary>
private static readonly ConcurrentDictionary<PropertyInfo, bool> _PropertyCache = new ConcurrentDictionary<PropertyInfo, bool>();
/// <summary>
/// 判断对象是否为原始类型或字符串
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static bool IsPrimitiveType(object obj) =>
obj is not null && (obj.GetType().IsPrimitive || obj is string or ValueType);
/// <summary>
/// 判断对象是否为集合类型(但不是字符串)
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static bool IsCollectionType(object obj) => obj is IEnumerable && obj is not string;
/// <summary>
/// 将对象转换为字典或列表
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static object ToDictionaryOrList(object obj)
{
if (obj == null) return null;
return obj switch
{
_ when IsPrimitiveType(obj) => obj,
IEnumerable enumerable => TransformCollection(enumerable),
_ => TransformObject(obj)
};
}
/// <summary>
/// 将集合转换为列表
/// </summary>
/// <param name="enumerable"></param>
/// <returns></returns>
private static List<object> TransformCollection(IEnumerable enumerable)
{
// 如果集合实现了 ICollection 接口,则使用其 Count 属性初始化列表容量
var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
foreach (var item in enumerable)
{
list.Add(ToDictionaryOrList(item));
}
return list;
}
// 将对象转换为字典
private static Dictionary<string, object> TransformObject(object obj)
{
var type = obj.GetType();
// 获取或创建该类型的属性访问器
var accessors = PropertyCache.GetOrAdd(type, t => CreatePropertyAccessors(t));
var keyValuePairs = new Dictionary<string, object>(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<PropertyAccessor>(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<Func<object, object>>(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<PropertyInfo, bool> propertyCache)
{
if (propertyCache.TryGetValue(property, out bool hasImagesAttribute))
{
return hasImagesAttribute;
}
hasImagesAttribute = property.GetCustomAttribute<ImagesAttribute>() != null;
propertyCache[property] = hasImagesAttribute;
return hasImagesAttribute;
}
// 属性访问器类,包含属性名、获取器和特性标志
private class PropertyAccessor
{
public string PropertyName { get; }
public Func<object, object> Getter { get; }
public bool HasImagesAttribute { get; }
public PropertyAccessor(string propertyName, Func<object, object> getter, bool hasImagesAttribute)
{
PropertyName = propertyName;
Getter = getter;
HasImagesAttribute = hasImagesAttribute;
}
}
}
[Obsolete]
public static class ObjectExtensions7
{
private static readonly ConcurrentDictionary<Type, PropertyAccessor[]> PropertyCache = new();
private static readonly ConcurrentDictionary<PropertyInfo, bool> _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<object> TransformCollection(IEnumerable enumerable)
{
var list = new List<object>(enumerable is ICollection collection ? collection.Count : 10);
foreach (var item in enumerable)
{
list.Add(ToDictionaryOrList(item));
}
return list;
}
private static Dictionary<string, object> TransformObject(object obj)
{
var type = obj.GetType();
var accessors = PropertyCache.GetOrAdd(type, CreatePropertyAccessors);
var keyValuePairs = new Dictionary<string, object>(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<ImagesAttribute>() != null);
return new PropertyAccessor(property.Name, getter, hasImagesAttribute);
}).ToArray();
}
private static Func<object, object> 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<Func<object, object>>(convertPropertyAccess, parameter).Compile();
}
private class PropertyAccessor
{
public string PropertyName { get; }
public Func<object, object> Getter { get; }
public bool HasImagesAttribute { get; }
public PropertyAccessor(string propertyName, Func<object, object> getter, bool hasImagesAttribute)
{
PropertyName = propertyName;
Getter = getter;
HasImagesAttribute = hasImagesAttribute;
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HuanMeng.DotNetCore.Utility;
/// <summary>
/// 字符串扩展
/// </summary>
public static class StringExtend
{
/// <summary>
/// 判断字符串是否包含中文字符(使用字符遍历)
/// </summary>
/// <param name="input">需要检查的字符串</param>
/// <returns>如果包含中文字符,则返回 true否则返回 false</returns>
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;
}
}