using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace ThingsGateway.NewLife.Reflection;
/// 反射工具类
///
/// 文档 https://newlifex.com/core/reflect
///
public static class Reflect
{
#region 静态
/// 当前反射提供者
public static IReflect Provider { get; set; }
static Reflect() => Provider = new DefaultReflect();// 如果需要使用快速反射,启用下面这一行//Provider = new EmitReflect();
#endregion
#region 反射获取
/// 根据名称获取类型。可搜索当前目录DLL,自动加载
/// 类型名
///
public static Type? GetTypeEx(this String typeName)
{
if (String.IsNullOrEmpty(typeName)) return null;
var type = Type.GetType(typeName);
if (type != null) return type;
return Provider.GetType(typeName, false);
}
/// 获取方法
/// 用于具有多个签名的同名方法的场合,不确定是否存在性能问题,不建议普通场合使用
/// 类型
/// 名称
/// 参数类型数组
///
public static MethodInfo? GetMethodEx(this Type type, String name, params Type[] paramTypes)
{
if (name.IsNullOrEmpty()) return null;
// 如果其中一个类型参数为空,得用别的办法
if (paramTypes.Length > 0 && paramTypes.Any(e => e == null)) return Provider.GetMethods(type, name, paramTypes.Length).FirstOrDefault();
return Provider.GetMethod(type, name, paramTypes);
}
/// 获取指定名称的方法集合,支持指定参数个数来匹配过滤
///
///
/// 参数个数,-1表示不过滤参数个数
///
public static MethodInfo[] GetMethodsEx(this Type type, String name, Int32 paramCount = -1)
{
if (name.IsNullOrEmpty()) return Array.Empty();
return Provider.GetMethods(type, name, paramCount);
}
/// 获取属性。搜索私有、静态、基类,优先返回大小写精确匹配成员
/// 类型
/// 名称
/// 忽略大小写
///
public static PropertyInfo? GetPropertyEx(this Type type, String name, Boolean ignoreCase = false)
{
if (String.IsNullOrEmpty(name)) return null;
return Provider.GetProperty(type, name, ignoreCase);
}
/// 获取字段。搜索私有、静态、基类,优先返回大小写精确匹配成员
/// 类型
/// 名称
/// 忽略大小写
///
public static FieldInfo? GetFieldEx(this Type type, String name, Boolean ignoreCase = false)
{
if (String.IsNullOrEmpty(name)) return null;
return Provider.GetField(type, name, ignoreCase);
}
/// 获取成员。搜索私有、静态、基类,优先返回大小写精确匹配成员
/// 类型
/// 名称
/// 忽略大小写
///
public static MemberInfo? GetMemberEx(this Type type, String name, Boolean ignoreCase = false)
{
if (String.IsNullOrEmpty(name)) return null;
return Provider.GetMember(type, name, ignoreCase);
}
/// 获取用于序列化的字段
/// 过滤特性的字段
///
///
///
public static IList GetFields(this Type type, Boolean baseFirst) => Provider.GetFields(type, baseFirst);
/// 获取用于序列化的属性
/// 过滤特性的属性和索引器
///
///
///
public static IList GetProperties(this Type type, Boolean baseFirst) => Provider.GetProperties(type, baseFirst);
#endregion
#region 反射调用
/// 反射创建指定类型的实例
/// 类型
/// 参数数组
///
[DebuggerHidden]
public static Object? CreateInstance(this Type type, params Object?[] parameters)
{
if (type == null) throw new ArgumentNullException(nameof(type));
return Provider.CreateInstance(type, parameters);
}
/// 反射调用指定对象的方法。target为类型时调用其静态方法
/// 要调用其方法的对象,如果要调用静态方法,则target是类型
/// 方法名
/// 方法参数
///
public static Object? Invoke(this Object target, String name, params Object?[] parameters)
{
if (target == null) throw new ArgumentNullException(nameof(target));
if (String.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
if (TryInvoke(target, name, out var value, parameters)) return value;
var type = GetType(target);
throw new XException("Cannot find method named {1} in class {0}!", type, name);
}
/// 反射调用指定对象的方法
/// 要调用其方法的对象,如果要调用静态方法,则target是类型
/// 方法名
/// 数值
/// 方法参数
/// 反射调用是否成功
public static Boolean TryInvoke(this Object target, String name, out Object? value, params Object?[] parameters)
{
value = null;
if (String.IsNullOrEmpty(name)) return false;
var type = GetType(target);
// 参数类型数组
var ps = parameters.Select(e => e?.GetType()).ToArray();
// 如果参数数组出现null,则无法精确匹配,可按参数个数进行匹配
var method = ps.Any(e => e == null) ? GetMethodEx(type, name) : GetMethodEx(type, name, ps!);
method ??= GetMethodsEx(type, name, ps.Length > 0 ? ps.Length : -1).FirstOrDefault();
if (method == null) return false;
value = Invoke(target, method, parameters);
return true;
}
/// 反射调用指定对象的方法
/// 要调用其方法的对象,如果要调用静态方法,则target是类型
/// 方法
/// 方法参数
///
[DebuggerHidden]
public static Object? Invoke(this Object? target, MethodBase method, params Object?[]? parameters)
{
//if (target == null) throw new ArgumentNullException("target");
if (method == null) throw new ArgumentNullException(nameof(method));
if (!method.IsStatic && target == null) throw new ArgumentNullException(nameof(target));
return Provider.Invoke(target, method, parameters);
}
/// 反射调用指定对象的方法
/// 要调用其方法的对象,如果要调用静态方法,则target是类型
/// 方法
/// 方法参数字典
///
[DebuggerHidden]
public static Object? InvokeWithParams(this Object? target, MethodBase method, IDictionary? parameters)
{
//if (target == null) throw new ArgumentNullException("target");
if (method == null) throw new ArgumentNullException(nameof(method));
if (!method.IsStatic && target == null) throw new ArgumentNullException(nameof(target));
return Provider.InvokeWithParams(target, method, parameters);
}
/// 获取目标对象指定名称的属性/字段值
/// 目标对象
/// 名称
/// 出错时是否抛出异常
///
[DebuggerHidden]
public static Object? GetValue(this Object target, String name, Boolean throwOnError = true)
{
if (target == null) throw new ArgumentNullException(nameof(target));
if (String.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
if (TryGetValue(target, name, out var value)) return value;
if (!throwOnError) return null;
var type = GetType(target);
throw new ArgumentException($"The [{name}] property or field does not exist in class [{type.FullName}].");
}
/// 获取目标对象指定名称的属性/字段值
/// 目标对象
/// 名称
/// 数值
/// 是否成功获取数值
internal static Boolean TryGetValue(this Object target, String name, out Object? value)
{
value = null;
if (String.IsNullOrEmpty(name)) return false;
var type = GetType(target);
var mi = type.GetMemberEx(name, true);
if (mi == null) return false;
value = target.GetValue(mi);
return true;
}
/// 获取目标对象的成员值
/// 目标对象
/// 成员
///
[DebuggerHidden]
public static Object? GetValue(this Object? target, MemberInfo member)
{
// 有可能跟普通的 PropertyInfo.GetValue(Object target) 搞混了
if (member == null && target is MemberInfo mi)
{
member = mi;
target = null;
}
//if (target is IModel model && member is PropertyInfo) return model[member.Name];
if (member is PropertyInfo property)
return Provider.GetValue(target, property);
else if (member is FieldInfo field)
return Provider.GetValue(target, field);
else
throw new ArgumentOutOfRangeException(nameof(member));
}
/// 设置目标对象指定名称的属性/字段值,若不存在返回false
/// 目标对象
/// 名称
/// 数值
/// 反射调用是否成功
[DebuggerHidden]
public static Boolean SetValue(this Object target, String name, Object? value)
{
if (String.IsNullOrEmpty(name)) return false;
//// 借助 IModel 优化取值赋值,有 IExtend 扩展属性的实体类过于复杂而不支持,例如IEntity就有脏数据问题
//if (target is IModel model && target is not IExtend)
//{
// model[name] = value;
// return true;
//}
var type = GetType(target);
var mi = type.GetMemberEx(name, true);
if (mi == null) return false;
target.SetValue(mi, value);
//throw new ArgumentException("The [{name}] property or field does not exist in class [{type.FullName}].");
return true;
}
/// 设置目标对象的成员值
/// 目标对象
/// 成员
/// 数值
[DebuggerHidden]
public static void SetValue(this Object target, MemberInfo member, Object? value)
{
//// 借助 IModel 优化取值赋值,有 IExtend 扩展属性的实体类过于复杂而不支持,例如IEntity就有脏数据问题
//if (target is IModel model && target is not IExtend && member is PropertyInfo)
// model[member.Name] = value;
//else
if (member is PropertyInfo pi)
Provider.SetValue(target, pi, value);
else if (member is FieldInfo fi)
Provider.SetValue(target, fi, value);
else
throw new ArgumentOutOfRangeException(nameof(member));
}
/// 从源对象拷贝数据到目标对象
/// 目标对象
/// 源对象
/// 递归深度拷贝,直接拷贝成员值而不是引用
/// 要忽略的成员
public static void Copy(this Object target, Object src, Boolean deep = false, params String[] excludes) => Provider.Copy(target, src, deep, excludes);
/// 从源字典拷贝数据到目标对象
/// 目标对象
/// 源字典
/// 递归深度拷贝,直接拷贝成员值而不是引用
public static void Copy(this Object target, IDictionary dic, Boolean deep = false) => Provider.Copy(target, dic, deep);
#endregion
#region 类型辅助
/// 获取一个类型的元素类型
/// 类型
///
public static Type? GetElementTypeEx(this Type type) => Provider.GetElementType(type);
/// 类型转换
/// 数值
///
///
public static Object? ChangeType(this Object? value, Type conversionType) => Provider.ChangeType(value, conversionType);
/// 类型转换
///
/// 数值
///
public static TResult? ChangeType(this Object? value)
{
if (value == null && typeof(TResult).IsValueType) return default;
if (value == null && typeof(TResult).IsNullable()) return (TResult?)(Object?)null;
if (value is TResult result) return result;
return (TResult?)ChangeType(value, typeof(TResult));
}
#if NET8_0_OR_GREATER
/// 类型转换
///
/// 数值
///
public static TResult? ChangeType(this String value) where TResult : IParsable
{
if (value is TResult result) return result;
// 支持IParsable接口
if (TResult.TryParse(value, null, out var rs)) return rs;
return default;
}
#endif
/// 获取类型的友好名称
/// 指定类型
/// 是否全名,包含命名空间
///
public static String GetName(this Type type, Boolean isfull = false) => Provider.GetName(type, isfull);
/// 从参数数组中获取类型数组
///
///
public static Type[] GetTypeArray(this Object?[]? args)
{
if (args == null) return Type.EmptyTypes;
var typeArray = new Type[args.Length];
for (var i = 0; i < typeArray.Length; i++)
{
var arg = args[i];
if (arg == null)
typeArray[i] = typeof(Object);
else
typeArray[i] = arg.GetType();
}
return typeArray;
}
/// 获取成员的类型,字段和属性是它们的类型,方法是返回类型,类型是自身
///
///
public static Type? GetMemberType(this MemberInfo member)
{
//return member.MemberType switch
//{
// MemberTypes.Constructor => (member as ConstructorInfo).DeclaringType,
// MemberTypes.Field => (member as FieldInfo).FieldType,
// MemberTypes.Method => (member as MethodInfo).ReturnType,
// MemberTypes.Property => (member as PropertyInfo).PropertyType,
// MemberTypes.TypeInfo or MemberTypes.NestedType => member as Type,
// _ => null,
//};
if (member is ConstructorInfo ctor) return ctor.DeclaringType;
if (member is FieldInfo field) return field.FieldType;
if (member is MethodInfo method) return method.ReturnType;
if (member is PropertyInfo property) return property.PropertyType;
if (member is Type type) return type;
return null;
}
/// 获取类型代码,支持可空类型
///
///
public static TypeCode GetTypeCode(this Type type) => type == null ? TypeCode.Empty : Type.GetTypeCode(Nullable.GetUnderlyingType(type) ?? type);
/// 是否基础类型。识别常见基元类型和String,支持可空类型
///
/// 基础类型可以方便的进行字符串转换,用于存储于传输。
/// 在序列化时,基础类型作为原子数据不可再次拆分,而复杂类型则可以进一步拆分。
/// 包括:Boolean/Char/SByte/Byte/Int16/UInt16/Int32/UInt32/Int64/UInt64/Single/Double/Decimal/DateTime/String/枚举,以及这些类型的可空类型
///
///
///
public static Boolean IsBaseType(this Type type)
{
type = Nullable.GetUnderlyingType(type) ?? type;
return Type.GetTypeCode(type) != TypeCode.Object;
}
/// 是否可空类型。继承泛型定义Nullable的类型
///
///
public static Boolean IsNullable(this Type type) => type.IsGenericType && !type.IsGenericTypeDefinition && type.GetGenericTypeDefinition() == typeof(Nullable<>);
/// 是否整数。Byte/Int16/Int32/Int64/SByte/UInt16/UInt32/UInt64
///
///
public static Boolean IsInt(this Type type)
{
var code = type.GetTypeCode();
return code >= TypeCode.SByte && code <= TypeCode.UInt64;
//return type.GetTypeCode() switch
//{
// TypeCode.Empty => false,
// TypeCode.Object => false,
// TypeCode.DBNull => false,
// TypeCode.Boolean => false,
// TypeCode.Char => false,
// TypeCode.Byte or TypeCode.SByte => true,
// TypeCode.Int16 or TypeCode.Int32 or TypeCode.Int64 => true,
// TypeCode.UInt16 or TypeCode.UInt32 or TypeCode.UInt64 => true,
// TypeCode.Single or TypeCode.Double or TypeCode.Decimal => false,
// TypeCode.DateTime => false,
// TypeCode.String => false,
// _ => false,
//};
}
/// 是否数字类型。包括整数、小数、字节等
///
///
public static Boolean IsNumber(this Type type)
{
var code = type.GetTypeCode();
return code >= TypeCode.SByte && code <= TypeCode.Decimal;
//return type.GetTypeCode() switch
//{
// TypeCode.Empty => false,
// TypeCode.Object => false,
// TypeCode.DBNull => false,
// TypeCode.Boolean => false,
// TypeCode.Char => false,
// TypeCode.Byte or TypeCode.SByte => true,
// TypeCode.Int16 or TypeCode.Int32 or TypeCode.Int64 => true,
// TypeCode.UInt16 or TypeCode.UInt32 or TypeCode.UInt64 => true,
// TypeCode.Single or TypeCode.Double or TypeCode.Decimal => true,
// TypeCode.DateTime => false,
// TypeCode.String => false,
// _ => false,
//};
}
/// 是否泛型列表
///
///
public static Boolean IsList(this Type type) => type?.IsGenericType == true && type.As(typeof(IList<>));
/// 是否泛型字典
///
///
public static Boolean IsDictionary(this Type type) => type?.IsGenericType == true && type.As(typeof(IDictionary<,>));
#endregion
#region 插件
/// 是否能够转为指定基类
///
///
///
public static Boolean As(this Type type, Type baseType) => Provider.As(type, baseType);
/// 是否能够转为指定基类
///
///
///
public static Boolean As(this Type type) => Provider.As(type, typeof(T));
/// 在指定程序集中查找指定基类的子类
/// 指定程序集
/// 基类或接口
///
public static IEnumerable GetSubclasses(this Assembly asm, Type baseType) => Provider.GetSubclasses(asm, baseType);
/// 在所有程序集中查找指定基类或接口的子类实现
/// 基类或接口
///
public static IEnumerable GetAllSubclasses(this Type baseType) => Provider.GetAllSubclasses(baseType);
#endregion
#region 辅助方法
/// 获取类型,如果target是Type类型,则表示要反射的是静态成员
/// 目标对象
///
static Type GetType(Object target)
{
if (target == null) throw new ArgumentNullException(nameof(target));
var type = target as Type;
if (type == null)
type = target.GetType();
//else
// target = null;
return type;
}
///// 判断某个类型是否可空类型
///// 类型
/////
//static Boolean IsNullable(Type type)
//{
// //if (type.IsValueType) return false;
// if (type.IsGenericType && !type.IsGenericTypeDefinition &&
// Object.ReferenceEquals(type.GetGenericTypeDefinition(), typeof(Nullable<>))) return true;
// return false;
//}
/// 把一个方法转为泛型委托,便于快速反射调用
///
///
///
///
public static TFunc? As(this MethodInfo method, object? target = null) where TFunc : class
{
if (method == null) return default;
var key = new DelegateCacheKey(method, typeof(TFunc), target);
var func = DelegateCache.Cache.GetOrAdd(
key,
_ =>
{
return (
target == null
? Delegate.CreateDelegate(typeof(TFunc), method, true) as TFunc
: Delegate.CreateDelegate(typeof(TFunc), target, method, true) as TFunc
);
});
return func;
}
/// 把一个方法转为泛型委托,便于快速反射调用
///
///
///
///
public static void RemoveCache(this MethodInfo method, object? target = null) where TFunc : class
{
if (method == null) return;
var key = new DelegateCacheKey(method, typeof(TFunc), target);
DelegateCache.Cache.TryRemove(key);
}
#endregion
}
public static class DelegateCache
{
public static readonly ExpiringDictionary Cache = new();
}
public readonly struct DelegateCacheKey : IEquatable
{
public readonly MethodInfo Method;
public readonly Type FuncType;
public readonly object? Target;
public DelegateCacheKey(MethodInfo method, Type funcType, object? target)
{
Method = method;
FuncType = funcType;
Target = target;
}
public bool Equals(DelegateCacheKey other) =>
Method.Equals(other.Method)
&& FuncType.Equals(other.FuncType)
&& ReferenceEquals(Target, other.Target);
public override bool Equals(object? obj) =>
obj is DelegateCacheKey other && Equals(other);
public override int GetHashCode()
{
unchecked
{
int hash = Method.GetHashCode();
hash = (hash * 397) ^ FuncType.GetHashCode();
if (Target != null)
hash = (hash * 397) ^ RuntimeHelpers.GetHashCode(Target); // 不受对象重写 GetHashCode 影响
return hash;
}
}
}