一 、反射概述
反射提供描述程序集、模块和类型的对象(Type 类型)。 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后调用其方法或访问其字段和属性。 如果代码中使用了特性,可以利用反射来访问它们。
反射在以下情况下很有用:
-
需要访问程序元数据中的特性时。
-
检查和实例化程序集中的类型。
-
在运行时构建新类型。
-
执行后期绑定,访问在运行时创建的类型上的方法。
二 、Type对象
Type:表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
如何获取Type?
1. Type t = typeof(String); String可以是其他类型
2. Type t = String.GetType();
3. Type t = Type.GetType("System.String"); 及相关重载,注意参数包含命名空间
更多方式参见 https://docs.microsoft.com/zh-cn/dotnet/api/system.type?view=netframework-4.7.2
三 、Assembly对象
Assembly:使用 Assembly 来定义和加载程序集,加载程序集清单中列出的模块,以及在此程序集中定位一个类型并创建一个它的实例。
如何获取Assembly?
1. 加载程序集的建议的方法是使用Load方法,它标识要按其显示名称加载的程序集 (例如,"System.Windows.Forms、 版本 = 2.0.0.0,区域性 = 中性,PublicKeyToken = b77a5c561934e089")。
Assembly assembly=Assembly.Load("System"); 参数为名称空间
2. LoadFile和LoadFrom方法为在其中必须由路径标识程序集的极少数情况下提供。
Assembly a = Assembly.LoadFile(@"D:C#ReflectTestReflectTestdllUtility.dll"); dll或exe全路径
Assembly a = Assembly.LoadForm(@"D:C#ReflectTestReflectTestdllUtility.dll");
3. ReflectionOnlyLoad和ReflectionOnlyLoadFrom方法可加载为反射,而不是执行程序集。 与Load,LoadForm类似
四 、获取指定程序集类的方法
public static void Main(string[] args) { Assembly a = Assembly.Load("ReflectTest"); Type t = a.GetType("ReflectTest.Program"); var isnt = Activator.CreateInstance(t); foreach (var method in t.GetMethods()) { //激活方法 method.Invoke(t, null); } }
参数由第二个入参确定,一般多个参数建议使用object传入(当入参变更时可以减少代码修改)
如需获取私有等方法可以使用重载public MethodInfo GetMethod(string name, BindingFlags bindingAttr);等借助BindingFlags对象实现。
五 、获取指定程序集类的属性
public static void Main(string[] args) { Assembly a = Assembly.Load("ReflectTest"); Type t = a.GetType("ReflectTest.Program"); var isnt = Activator.CreateInstance(t); foreach (var propt in t.GetProperties()) { Console.WriteLine(propt.Name); } }
应用:利用反射将dataTable填充至泛型对象
/// <summary> /// DataTable利用泛型填充实体类 /// </summary> /// <typeparam name="T">实体类</typeparam> /// <param name="table">dt</param> /// <returns></returns> public static IList<T> DataTableToList<T>(DataTable table) { IList<T> list = new List<T>(); T t = default(T); PropertyInfo[] propertypes = null; string tempName = string.Empty; foreach (DataRow row in table.Rows) { t = Activator.CreateInstance<T>(); propertypes = t.GetType().GetProperties(); foreach (PropertyInfo pro in propertypes) { tempName = pro.Name; if (table.Columns.Contains(tempName)) { string value = row[tempName].ToString(); pro.SetValue(t, value, null); } } list.Add(t); } return list; }