using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Resources; using System.Text; using Masuit.Tools.Systems; namespace Masuit.Tools.Reflection { /// /// 反射操作辅助类,如获取或设置字段、属性的值等反射信息。 /// public static class ReflectionUtil { #region 属性字段设置 public static BindingFlags bf = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; /// /// 执行方法 /// /// 反射对象 /// 方法名,区分大小写 /// 方法参数 /// 约束返回的T必须是引用类型 /// T类型 public static T InvokeMethod(this object obj, string methodName, object[] args) { return (T)obj.GetType().GetMethod(methodName, args.Select(o => o.GetType()).ToArray()).Invoke(obj, args); } /// /// 执行方法 /// /// 反射对象 /// 方法名,区分大小写 /// 方法参数 /// T类型 public static void InvokeMethod(this object obj, string methodName, object[] args) { var type = obj.GetType(); type.GetMethod(methodName, args.Select(o => o.GetType()).ToArray()).Invoke(obj, args); } /// /// 设置字段 /// /// 反射对象 /// 字段名 /// 值 public static void SetField(this T obj, string name, object value) where T : class { SetProperty(obj, name, value); } /// /// 获取字段 /// /// 反射对象 /// 字段名 /// 约束返回的T必须是引用类型 /// T类型 public static T GetField(this object obj, string name) { return GetProperty(obj, name); } /// /// 获取所有的字段信息 /// /// 反射对象 /// 字段信息 public static FieldInfo[] GetFields(this object obj) { FieldInfo[] fieldInfos = obj.GetType().GetFields(bf); return fieldInfos; } /// /// 设置属性 /// /// 反射对象 /// 属性名 /// 值 public static string SetProperty(this T obj, string name, object value) where T : class { var parameter = Expression.Parameter(typeof(T), "e"); var property = Expression.PropertyOrField(parameter, name); var before = Expression.Lambda(property, parameter).Compile().DynamicInvoke(obj); if (value == before) { return value?.ToString(); } if (property.Type.IsGenericType && property.Type.GetGenericTypeDefinition() == typeof(Nullable<>)) { typeof(T).GetProperty(name)?.SetValue(obj, value); } else { var valueExpression = Expression.Parameter(property.Type, "v"); var assign = Expression.Assign(property, valueExpression); Expression.Lambda(assign, parameter, valueExpression).Compile().DynamicInvoke(obj, value); } return before.ToJsonString(); } private static readonly ConcurrentDictionary DelegateCache = new(); /// /// 获取属性 /// /// 反射对象 /// 属性名 /// 约束返回的T必须是引用类型 /// T类型 public static T GetProperty(this object obj, string name) { var type = obj.GetType(); if (DelegateCache.TryGetValue(type.Name + "." + name, out var func)) { return (T)func.DynamicInvoke(obj); } var parameter = Expression.Parameter(type, "e"); var property = Expression.PropertyOrField(parameter, name); func = Expression.Lambda(property, parameter).Compile(); DelegateCache.TryAdd(type.Name + "." + name, func); return (T)func.DynamicInvoke(obj); } /// /// 获取所有的属性信息 /// /// 反射对象 /// 属性信息 public static PropertyInfo[] GetProperties(this object obj) { return obj.GetType().GetProperties(bf); } #endregion 属性字段设置 #region 获取Description /// /// 获取枚举值的Description信息 /// /// 枚举值 /// 要格式化的对象 /// 如果未找到DescriptionAttribute则返回null或返回类型描述 public static string GetDescription(this Enum value, params object[] args) { if (value == null) { throw new ArgumentNullException(nameof(value)); } var type = value.GetType(); if (!Enum.IsDefined(type, value)) { return value.ToString(); } FieldInfo fi = type.GetField(value.ToString()); var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); var text = attributes.Length > 0 ? attributes[0].Description : value.ToString(); if (args is { Length: > 0 }) { return string.Format(text, args); } return text; } /// /// 获取枚举值的Description信息 /// /// 枚举值 /// 如果未找到DescriptionAttribute则返回null或返回类型描述 public static EnumDescriptionAttribute GetEnumDescription(this Enum value) { return GetEnumDescriptions(value).FirstOrDefault(); } /// /// 获取枚举值的Description信息 /// /// 枚举值 /// 如果未找到DescriptionAttribute则返回null或返回类型描述 public static NullableDictionary GetTypedEnumDescriptions(this Enum value) { return GetEnumDescriptions(value).ToDictionarySafety(a => a.Language, a => (Description: a.Description, Display: a.Display)); } /// /// 获取枚举值的Description信息 /// /// 枚举值 /// 如果未找到DescriptionAttribute则返回null或返回类型描述 public static IEnumerable GetEnumDescriptions(this Enum value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } var type = value.GetType(); if (!Enum.IsDefined(type, value)) { return new List(); } FieldInfo fi = type.GetField(value.ToString()); return fi.GetCustomAttributes(typeof(EnumDescriptionAttribute), false).OfType(); } /// /// 根据成员信息获取Description信息 /// /// 成员信息 /// 如果未找到DescriptionAttribute则返回null或返回类型描述 public static string GetDescription(this MemberInfo member) { return GetDescription(member, null); } /// /// 根据成员信息获取Description信息 /// /// 成员信息 /// 格式化占位对象 /// 如果未找到DescriptionAttribute则返回null或返回类型描述 public static string GetDescription(this MemberInfo member, params object[] args) { if (member == null) { throw new ArgumentNullException(nameof(member)); } return member.IsDefined(typeof(DescriptionAttribute), false) ? member.GetAttribute().Description : string.Empty; } #endregion 获取Description /// /// 获取对象的Attribute /// /// public static T GetAttribute(this ICustomAttributeProvider provider) where T : Attribute { var attributes = provider.GetCustomAttributes(typeof(T), true); return attributes.Length > 0 ? attributes[0] as T : null; } /// /// 获取对象的Attributes /// /// public static IEnumerable GetAttributes(this ICustomAttributeProvider provider) where T : Attribute { return provider.GetCustomAttributes(typeof(T), true).OfType(); } #region 资源获取 /// /// 根据资源名称获取图片资源流 /// /// /// 资源的名称 /// 数据流 public static Stream GetImageResource(this Assembly _, string resourceName) { Assembly asm = Assembly.GetExecutingAssembly(); return asm.GetManifestResourceStream(resourceName); } /// /// 获取程序集资源的文本资源 /// /// 程序集中的某一对象类型 /// 资源项名称 /// 资源的根名称。例如,名为“MyResource.en-US.resources”的资源文件的根名称为“MyResource”。 public static string GetStringRes(this Type assemblyType, string resName, string resourceHolder) { Assembly thisAssembly = Assembly.GetAssembly(assemblyType); ResourceManager rm = new ResourceManager(resourceHolder, thisAssembly); return rm.GetString(resName); } /// /// 获取程序集嵌入资源的文本形式 /// /// 程序集中的某一对象类型 /// 字符集编码 /// 嵌入资源相对路径 /// 如没找到该资源则返回空字符 public static string GetManifestString(this Type assemblyType, string charset, string resName) { Assembly asm = Assembly.GetAssembly(assemblyType); Stream st = asm.GetManifestResourceStream(string.Concat(assemblyType.Namespace, ".", resName.Replace("/", "."))); if (st == null) { return ""; } int iLen = (int)st.Length; byte[] bytes = new byte[iLen]; st.Read(bytes, 0, iLen); return Encoding.GetEncoding(charset).GetString(bytes); } #endregion 资源获取 #region 创建实例 /// /// 获取默认实例 /// /// 类型 /// public static object GetInstance(this Type type) { return GetInstance(type, null); } /// /// 获取默认实例 /// /// 类型 /// public static T GetInstance(this Type type) where T : class, new() { return GetInstance(type, null); } /// /// 获取默认实例 /// /// 类型 /// public static T GetInstance(string type) where T : class, new() { return GetInstance(Type.GetType(type), null); } /// /// 获取默认实例 /// /// 类型 /// public static object GetInstance(string type) { return GetInstance(Type.GetType(type), null); } /// /// 获取一个构造参数的实例 /// /// 参数类型 /// /// 实例类型 /// 参数值 /// public static T GetInstance(this Type type, TArg argument) where T : class, new() { return GetInstance(type, argument, null); } /// /// 获取一个构造参数的实例 /// /// 参数类型 /// /// 实例类型 /// 参数值 /// public static T GetInstance(string type, TArg argument) where T : class, new() { return GetInstance(Type.GetType(type), argument, null); } /// /// 获取2个构造参数的实例 /// /// 参数类型 /// 参数类型 /// /// 实例类型 /// 参数值 /// 参数值 /// public static T GetInstance(this Type type, TArg1 argument1, TArg2 argument2) where T : class, new() { return GetInstance(type, argument1, argument2, null); } /// /// 获取2个构造参数的实例 /// /// 参数类型 /// 参数类型 /// /// 实例类型 /// 参数值 /// 参数值 /// public static T GetInstance(string type, TArg1 argument1, TArg2 argument2) where T : class, new() { return GetInstance(Type.GetType(type), argument1, argument2, null); } /// /// 获取3个构造参数的实例 /// /// 参数类型 /// 参数类型 /// 参数类型 /// /// 实例类型 /// 参数值 /// 参数值 /// 参数值 /// public static T GetInstance(this Type type, TArg1 argument1, TArg2 argument2, TArg3 argument3) where T : class, new() { return InstanceCreationFactory.CreateInstanceOf(type, argument1, argument2, argument3); } /// /// 获取3个构造参数的实例 /// /// 参数类型 /// 参数类型 /// 参数类型 /// /// 实例类型 /// 参数值 /// 参数值 /// 参数值 /// public static T GetInstance(string type, TArg1 argument1, TArg2 argument2, TArg3 argument3) where T : class, new() { return InstanceCreationFactory.CreateInstanceOf(Type.GetType(type), argument1, argument2, argument3); } private class TypeToIgnore { } private static class InstanceCreationFactory where TObject : class, new() { private static readonly Dictionary> InstanceCreationMethods = new Dictionary>(); public static TObject CreateInstanceOf(Type type, TArg1 arg1, TArg2 arg2, TArg3 arg3) { CacheInstanceCreationMethodIfRequired(type); return InstanceCreationMethods[type](arg1, arg2, arg3); } private static void CacheInstanceCreationMethodIfRequired(Type type) { if (InstanceCreationMethods.ContainsKey(type)) { return; } var argumentTypes = new[] { typeof(TArg1), typeof(TArg2), typeof(TArg3) }; Type[] constructorArgumentTypes = argumentTypes.Where(t => t != typeof(TypeToIgnore)).ToArray(); var constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, constructorArgumentTypes, new ParameterModifier[0]); var lamdaParameterExpressions = new[] { Expression.Parameter(typeof(TArg1), "param1"), Expression.Parameter(typeof(TArg2), "param2"), Expression.Parameter(typeof(TArg3), "param3") }; var constructorParameterExpressions = lamdaParameterExpressions.Take(constructorArgumentTypes.Length).ToArray(); var constructorCallExpression = Expression.New(constructor, constructorParameterExpressions); var constructorCallingLambda = Expression.Lambda>(constructorCallExpression, lamdaParameterExpressions).Compile(); InstanceCreationMethods[type] = constructorCallingLambda; } } #endregion 创建实例 } }