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