using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
namespace Common.Utils;
///
/// 属性访问器(用于缓存,提高反射性能)
///
/// 类型
internal class PropertyAccessor
{
public Func? Getter { get; set; }
public Action? Setter { get; set; }
public PropertyInfo PropertyInfo { get; set; }
public PropertyAccessor(PropertyInfo propertyInfo)
{
PropertyInfo = propertyInfo;
}
}
///
/// 反射工具类
/// 提供类型扫描、属性访问、特性读取等功能,并通过缓存提高性能
///
public static class ReflectionHelper
{
// 属性访问器缓存
private static readonly ConcurrentDictionary> PropertyAccessorCache = new();
// 特性缓存
private static readonly ConcurrentDictionary AttributeCache = new();
// 类型缓描
private static readonly ConcurrentDictionary TypeCache = new();
#region 类型扫描
///
/// 从程序集中获取所有类型
///
/// 程序集
/// 是否使用缓存(默认 true)
/// 类型数组
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;
}
///
/// 从当前程序集中查找指定基类的所有子类
///
/// 基类类型
/// 是否包含抽象类(默认 false)
/// 子类类型列表
public static List FindSubclassesOf(bool includeAbstract = false)
{
return FindSubclassesOf(typeof(TBase), includeAbstract);
}
///
/// 从当前程序集中查找指定基类的所有子类
///
public static List 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();
}
///
/// 从指定程序集中查找实现指定接口的所有类型
///
/// 接口类型
/// 程序集
/// 是否包含抽象类(默认 false)
/// 实现类型列表
public static List FindImplementationsOf(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();
}
///
/// 查找带有指定特性的所有类型
///
/// 特性类型
/// 程序集
/// 是否搜索继承链(默认 true)
/// 类型列表
public static List FindTypesWithAttribute(Assembly assembly, bool inherit = true)
where TAttribute : Attribute
{
return GetTypes(assembly)
.Where(t => t.GetCustomAttribute(inherit) != null)
.ToList();
}
#endregion
#region 属性访问(高性能)
///
/// 获取属性值(使用缓存的访问器,比直接反射快)
///
public static object? GetPropertyValue(T obj, string propertyName)
{
var accessor = GetPropertyAccessor(propertyName);
return accessor?.Getter?.Invoke(obj);
}
///
/// 设置属性值(使用缓存的访问器)
///
public static void SetPropertyValue(T obj, string propertyName, object? value)
{
var accessor = GetPropertyAccessor(propertyName);
accessor?.Setter?.Invoke(obj, value);
}
///
/// 获取属性访问器(内部使用表达式树生成,首次慢,后续快)
///
private static PropertyAccessor? GetPropertyAccessor(string propertyName)
{
var type = typeof(T);
var cache = PropertyAccessorCache.GetOrAdd(type, _ => new Dictionary());
lock (cache)
{
if (cache.TryGetValue(propertyName, out var cachedAccessor))
return (PropertyAccessor)cachedAccessor;
var propertyInfo = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
return null;
var accessor = new PropertyAccessor(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>(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>(assign, instance, value).Compile();
}
cache[propertyName] = accessor;
return accessor;
}
}
///
/// 获取所有属性名称
///
public static List GetPropertyNames(BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
{
return typeof(T).GetProperties(flags).Select(p => p.Name).ToList();
}
///
/// 获取所有属性信息
///
public static PropertyInfo[] GetProperties(BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
{
return typeof(T).GetProperties(flags);
}
#endregion
#region 特性读取(带缓存)
///
/// 获取类型的特性(带缓存)
///
public static TAttribute? GetAttribute(Type type, bool inherit = true)
where TAttribute : Attribute
{
var attributes = GetAttributes(type, inherit);
return attributes.FirstOrDefault();
}
///
/// 获取类型的所有指定特性(带缓存)
///
public static TAttribute[] GetAttributes(Type type, bool inherit = true)
where TAttribute : Attribute
{
var cached = AttributeCache.GetOrAdd(type, _ => type.GetCustomAttributes(inherit).ToArray());
return cached.OfType().ToArray();
}
///
/// 获取成员的特性(带缓存)
///
public static TAttribute? GetAttribute(MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
var attributes = GetAttributes(member, inherit);
return attributes.FirstOrDefault();
}
///
/// 获取成员的所有指定特性(带缓存)
///
public static TAttribute[] GetAttributes(MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
var cached = AttributeCache.GetOrAdd(member, _ => member.GetCustomAttributes(inherit).ToArray());
return cached.OfType().ToArray();
}
///
/// 判断类型是否有指定特性
///
public static bool HasAttribute(Type type, bool inherit = true)
where TAttribute : Attribute
{
return GetAttribute(type, inherit) != null;
}
///
/// 判断成员是否有指定特性
///
public static bool HasAttribute(MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return GetAttribute(member, inherit) != null;
}
#endregion
#region 创建实例
///
/// 创建类型实例(使用无参构造函数)
///
public static T? CreateInstance() where T : class
{
return Activator.CreateInstance();
}
///
/// 创建类型实例(使用无参构造函数)
///
public static object? CreateInstance(Type type)
{
return Activator.CreateInstance(type);
}
///
/// 创建类型实例(使用有参构造函数)
///
public static object? CreateInstance(Type type, params object[] args)
{
return Activator.CreateInstance(type, args);
}
///
/// 尝试创建类型实例
///
public static bool TryCreateInstance(out T? instance) where T : class
{
try
{
instance = CreateInstance();
return instance != null;
}
catch
{
instance = null;
return false;
}
}
#endregion
#region 属性复制
///
/// 将源对象的属性值复制到目标对象(同名属性)
///
/// 源类型
/// 目标类型
/// 源对象
/// 目标对象
/// 是否忽略属性名大小写(默认 false)
public static void CopyProperties(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);
}
}
///
/// 创建目标类型实例并复制属性
///
public static TTarget? MapTo(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 方法调用
///
/// 调用对象的方法
///
/// 对象实例
/// 方法名
/// 参数
/// 方法返回值
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);
}
///
/// 调用静态方法
///
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 类型判断
///
/// 判断类型是否为可空类型
///
public static bool IsNullableType(Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
///
/// 获取可空类型的基础类型
///
public static Type GetUnderlyingType(Type type)
{
return Nullable.GetUnderlyingType(type) ?? type;
}
///
/// 判断类型是否为值类型
///
public static bool IsValueType(Type type)
{
return type.IsValueType;
}
///
/// 判断类型是否为引用类型
///
public static bool IsReferenceType(Type type)
{
return !type.IsValueType;
}
///
/// 判断类型是否为数字类型
///
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);
}
///
/// 判断类型是否为集合类型
///
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 泛型操作
///
/// 判断类型是否为泛型类型
///
public static bool IsGenericType(Type type)
{
return type.IsGenericType;
}
///
/// 获取泛型参数类型
///
public static Type[] GetGenericArguments(Type type)
{
return type.GetGenericArguments();
}
///
/// 构造泛型类型(例如:List<> + int => List)
///
public static Type MakeGenericType(Type genericTypeDefinition, params Type[] typeArguments)
{
return genericTypeDefinition.MakeGenericType(typeArguments);
}
#endregion
#region 缓存管理
///
/// 清除所有缓存
///
public static void ClearCache()
{
PropertyAccessorCache.Clear();
AttributeCache.Clear();
TypeCache.Clear();
}
///
/// 清除属性访问器缓存
///
public static void ClearPropertyAccessorCache()
{
PropertyAccessorCache.Clear();
}
///
/// 清除特性缓存
///
public static void ClearAttributeCache()
{
AttributeCache.Clear();
}
///
/// 清除类型缓存
///
public static void ClearTypeCache()
{
TypeCache.Clear();
}
#endregion
}