A:common基础功能及测试

This commit is contained in:
jimmy committed 2025-11-14 10:22:34 +08:00
1 parent 9ffa70acde
commit 237cbd8788
11 files changed
+5929 -32

No files matched your search

+525
View File
@@ -0,0 +1,525 @@
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
namespace Common.Utils;
/// <summary>
/// 属性访问器(用于缓存,提高反射性能)
/// </summary>
/// <typeparam name="T">类型</typeparam>
internal class PropertyAccessor<T>
{
public Func<T, object?>? Getter { get; set; }
public Action<T, object?>? Setter { get; set; }
public PropertyInfo PropertyInfo { get; set; }
public PropertyAccessor(PropertyInfo propertyInfo)
{
PropertyInfo = propertyInfo;
}
}
/// <summary>
/// 反射工具类
/// 提供类型扫描、属性访问、特性读取等功能,并通过缓存提高性能
/// </summary>
public static class ReflectionHelper
{
// 属性访问器缓存
private static readonly ConcurrentDictionary<Type, Dictionary<string, object>> PropertyAccessorCache = new();
// 特性缓存
private static readonly ConcurrentDictionary<MemberInfo, object[]> AttributeCache = new();
// 类型缓描
private static readonly ConcurrentDictionary<Assembly, Type[]> TypeCache = new();
#region 类型扫描
/// <summary>
/// 从程序集中获取所有类型
/// </summary>
/// <param name="assembly">程序集</param>
/// <param name="useCache">是否使用缓存(默认 true)</param>
/// <returns>类型数组</returns>
public static Type[] GetTypes(Assembly assembly, bool useCache = true)
{
if (useCache && TypeCache.TryGetValue(assembly, out var cachedTypes))
return cachedTypes;
var types = assembly.GetTypes();
if (useCache)
TypeCache.TryAdd(assembly, types);
return types;
}
/// <summary>
/// 从当前程序集中查找指定基类的所有子类
/// </summary>
/// <typeparam name="TBase">基类类型</typeparam>
/// <param name="includeAbstract">是否包含抽象类(默认 false)</param>
/// <returns>子类类型列表</returns>
public static List<Type> FindSubclassesOf<TBase>(bool includeAbstract = false)
{
return FindSubclassesOf(typeof(TBase), includeAbstract);
}
/// <summary>
/// 从当前程序集中查找指定基类的所有子类
/// </summary>
public static List<Type> FindSubclassesOf(Type baseType, bool includeAbstract = false)
{
var assembly = Assembly.GetCallingAssembly();
return GetTypes(assembly)
.Where(t => t.IsClass && baseType.IsAssignableFrom(t) && t != baseType)
.Where(t => includeAbstract || !t.IsAbstract)
.ToList();
}
/// <summary>
/// 从指定程序集中查找实现指定接口的所有类型
/// </summary>
/// <typeparam name="TInterface">接口类型</typeparam>
/// <param name="assembly">程序集</param>
/// <param name="includeAbstract">是否包含抽象类(默认 false)</param>
/// <returns>实现类型列表</returns>
public static List<Type> FindImplementationsOf<TInterface>(Assembly assembly, bool includeAbstract = false)
{
var interfaceType = typeof(TInterface);
return GetTypes(assembly)
.Where(t => t.IsClass && interfaceType.IsAssignableFrom(t) && t != interfaceType)
.Where(t => includeAbstract || !t.IsAbstract)
.ToList();
}
/// <summary>
/// 查找带有指定特性的所有类型
/// </summary>
/// <typeparam name="TAttribute">特性类型</typeparam>
/// <param name="assembly">程序集</param>
/// <param name="inherit">是否搜索继承链(默认 true)</param>
/// <returns>类型列表</returns>
public static List<Type> FindTypesWithAttribute<TAttribute>(Assembly assembly, bool inherit = true)
where TAttribute : Attribute
{
return GetTypes(assembly)
.Where(t => t.GetCustomAttribute<TAttribute>(inherit) != null)
.ToList();
}
#endregion
#region 属性访问(高性能)
/// <summary>
/// 获取属性值(使用缓存的访问器,比直接反射快)
/// </summary>
public static object? GetPropertyValue<T>(T obj, string propertyName)
{
var accessor = GetPropertyAccessor<T>(propertyName);
return accessor?.Getter?.Invoke(obj);
}
/// <summary>
/// 设置属性值(使用缓存的访问器)
/// </summary>
public static void SetPropertyValue<T>(T obj, string propertyName, object? value)
{
var accessor = GetPropertyAccessor<T>(propertyName);
accessor?.Setter?.Invoke(obj, value);
}
/// <summary>
/// 获取属性访问器(内部使用表达式树生成,首次慢,后续快)
/// </summary>
private static PropertyAccessor<T>? GetPropertyAccessor<T>(string propertyName)
{
var type = typeof(T);
var cache = PropertyAccessorCache.GetOrAdd(type, _ => new Dictionary<string, object>());
lock (cache)
{
if (cache.TryGetValue(propertyName, out var cachedAccessor))
return (PropertyAccessor<T>)cachedAccessor;
var propertyInfo = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
return null;
var accessor = new PropertyAccessor<T>(propertyInfo);
// 使用表达式树生成 Getter
if (propertyInfo.CanRead)
{
var instance = Expression.Parameter(type, "instance");
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.Convert(property, typeof(object));
accessor.Getter = Expression.Lambda<Func<T, object?>>(convert, instance).Compile();
}
// 使用表达式树生成 Setter
if (propertyInfo.CanWrite)
{
var instance = Expression.Parameter(type, "instance");
var value = Expression.Parameter(typeof(object), "value");
var convert = Expression.Convert(value, propertyInfo.PropertyType);
var property = Expression.Property(instance, propertyInfo);
var assign = Expression.Assign(property, convert);
accessor.Setter = Expression.Lambda<Action<T, object?>>(assign, instance, value).Compile();
}
cache[propertyName] = accessor;
return accessor;
}
}
/// <summary>
/// 获取所有属性名称
/// </summary>
public static List<string> GetPropertyNames<T>(BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
{
return typeof(T).GetProperties(flags).Select(p => p.Name).ToList();
}
/// <summary>
/// 获取所有属性信息
/// </summary>
public static PropertyInfo[] GetProperties<T>(BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
{
return typeof(T).GetProperties(flags);
}
#endregion
#region 特性读取(带缓存)
/// <summary>
/// 获取类型的特性(带缓存)
/// </summary>
public static TAttribute? GetAttribute<TAttribute>(Type type, bool inherit = true)
where TAttribute : Attribute
{
var attributes = GetAttributes<TAttribute>(type, inherit);
return attributes.FirstOrDefault();
}
/// <summary>
/// 获取类型的所有指定特性(带缓存)
/// </summary>
public static TAttribute[] GetAttributes<TAttribute>(Type type, bool inherit = true)
where TAttribute : Attribute
{
var cached = AttributeCache.GetOrAdd(type, _ => type.GetCustomAttributes(inherit).ToArray());
return cached.OfType<TAttribute>().ToArray();
}
/// <summary>
/// 获取成员的特性(带缓存)
/// </summary>
public static TAttribute? GetAttribute<TAttribute>(MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
var attributes = GetAttributes<TAttribute>(member, inherit);
return attributes.FirstOrDefault();
}
/// <summary>
/// 获取成员的所有指定特性(带缓存)
/// </summary>
public static TAttribute[] GetAttributes<TAttribute>(MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
var cached = AttributeCache.GetOrAdd(member, _ => member.GetCustomAttributes(inherit).ToArray());
return cached.OfType<TAttribute>().ToArray();
}
/// <summary>
/// 判断类型是否有指定特性
/// </summary>
public static bool HasAttribute<TAttribute>(Type type, bool inherit = true)
where TAttribute : Attribute
{
return GetAttribute<TAttribute>(type, inherit) != null;
}
/// <summary>
/// 判断成员是否有指定特性
/// </summary>
public static bool HasAttribute<TAttribute>(MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return GetAttribute<TAttribute>(member, inherit) != null;
}
#endregion
#region 创建实例
/// <summary>
/// 创建类型实例(使用无参构造函数)
/// </summary>
public static T? CreateInstance<T>() where T : class
{
return Activator.CreateInstance<T>();
}
/// <summary>
/// 创建类型实例(使用无参构造函数)
/// </summary>
public static object? CreateInstance(Type type)
{
return Activator.CreateInstance(type);
}
/// <summary>
/// 创建类型实例(使用有参构造函数)
/// </summary>
public static object? CreateInstance(Type type, params object[] args)
{
return Activator.CreateInstance(type, args);
}
/// <summary>
/// 尝试创建类型实例
/// </summary>
public static bool TryCreateInstance<T>(out T? instance) where T : class
{
try
{
instance = CreateInstance<T>();
return instance != null;
}
catch
{
instance = null;
return false;
}
}
#endregion
#region 属性复制
/// <summary>
/// 将源对象的属性值复制到目标对象(同名属性)
/// </summary>
/// <typeparam name="TSource">源类型</typeparam>
/// <typeparam name="TTarget">目标类型</typeparam>
/// <param name="source">源对象</param>
/// <param name="target">目标对象</param>
/// <param name="ignoreCase">是否忽略属性名大小写(默认 false)</param>
public static void CopyProperties<TSource, TTarget>(TSource source, TTarget target, bool ignoreCase = false)
{
if (source == null || target == null)
return;
var sourceType = typeof(TSource);
var targetType = typeof(TTarget);
var sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanRead)
.ToList();
var targetProperties = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanWrite)
.ToDictionary(
p => p.Name,
p => p,
ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal
);
foreach (var sourceProp in sourceProperties)
{
if (targetProperties.TryGetValue(sourceProp.Name, out var targetProp))
{
// 检查类型是否兼容
if (targetProp.PropertyType.IsAssignableFrom(sourceProp.PropertyType))
{
var value = sourceProp.GetValue(source);
targetProp.SetValue(target, value);
}
}
}
}
/// <summary>
/// 创建目标类型实例并复制属性
/// </summary>
public static TTarget? MapTo<TSource, TTarget>(TSource source, bool ignoreCase = false)
where TTarget : class, new()
{
if (source == null)
return null;
var target = new TTarget();
CopyProperties(source, target, ignoreCase);
return target;
}
#endregion
#region 方法调用
/// <summary>
/// 调用对象的方法
/// </summary>
/// <param name="obj">对象实例</param>
/// <param name="methodName">方法名</param>
/// <param name="parameters">参数</param>
/// <returns>方法返回值</returns>
public static object? InvokeMethod(object obj, string methodName, params object[] parameters)
{
var type = obj.GetType();
var method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance);
if (method == null)
throw new InvalidOperationException($"Method '{methodName}' not found on type '{type.FullName}'");
return method.Invoke(obj, parameters);
}
/// <summary>
/// 调用静态方法
/// </summary>
public static object? InvokeStaticMethod(Type type, string methodName, params object[] parameters)
{
var method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static);
if (method == null)
throw new InvalidOperationException($"Static method '{methodName}' not found on type '{type.FullName}'");
return method.Invoke(null, parameters);
}
#endregion
#region 类型判断
/// <summary>
/// 判断类型是否为可空类型
/// </summary>
public static bool IsNullableType(Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
/// <summary>
/// 获取可空类型的基础类型
/// </summary>
public static Type GetUnderlyingType(Type type)
{
return Nullable.GetUnderlyingType(type) ?? type;
}
/// <summary>
/// 判断类型是否为值类型
/// </summary>
public static bool IsValueType(Type type)
{
return type.IsValueType;
}
/// <summary>
/// 判断类型是否为引用类型
/// </summary>
public static bool IsReferenceType(Type type)
{
return !type.IsValueType;
}
/// <summary>
/// 判断类型是否为数字类型
/// </summary>
public static bool IsNumericType(Type type)
{
type = GetUnderlyingType(type);
return type == typeof(byte) || type == typeof(sbyte) ||
type == typeof(short) || type == typeof(ushort) ||
type == typeof(int) || type == typeof(uint) ||
type == typeof(long) || type == typeof(ulong) ||
type == typeof(float) || type == typeof(double) ||
type == typeof(decimal);
}
/// <summary>
/// 判断类型是否为集合类型
/// </summary>
public static bool IsCollectionType(Type type)
{
return type.IsArray ||
(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) ||
type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>));
}
#endregion
#region 泛型操作
/// <summary>
/// 判断类型是否为泛型类型
/// </summary>
public static bool IsGenericType(Type type)
{
return type.IsGenericType;
}
/// <summary>
/// 获取泛型参数类型
/// </summary>
public static Type[] GetGenericArguments(Type type)
{
return type.GetGenericArguments();
}
/// <summary>
/// 构造泛型类型(例如:List<> + int => List<int>)
/// </summary>
public static Type MakeGenericType(Type genericTypeDefinition, params Type[] typeArguments)
{
return genericTypeDefinition.MakeGenericType(typeArguments);
}
#endregion
#region 缓存管理
/// <summary>
/// 清除所有缓存
/// </summary>
public static void ClearCache()
{
PropertyAccessorCache.Clear();
AttributeCache.Clear();
TypeCache.Clear();
}
/// <summary>
/// 清除属性访问器缓存
/// </summary>
public static void ClearPropertyAccessorCache()
{
PropertyAccessorCache.Clear();
}
/// <summary>
/// 清除特性缓存
/// </summary>
public static void ClearAttributeCache()
{
AttributeCache.Clear();
}
/// <summary>
/// 清除类型缓存
/// </summary>
public static void ClearTypeCache()
{
TypeCache.Clear();
}
#endregion
}