[C#] 反射
反射
简介
反射是 .NET中的重要机制,通过反射,可以在运行时获得程序或程序集中类型(包括 class、struct、delegate、interface 和 enum 等)的成员和成员的信息。
通过反射,即可对每一种类型了如指掌,并且也可以通过反射创建、调用和访问对象,即便在编译时不确定该对象的类型。
程序集包含模块,模块包含类型,而类型包含成员。反射提供封装程序集、模块和类型的对象。可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。
优缺点
优点:
- 提高了程序的灵活性和扩展性;
- 降低耦合性;
- 它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
缺点:
- 性能:使用反射基本上是一种解释操作,从理论上讲使用反射远慢于直接代码;
- 可读性降低。
反射的类型成员信息
-
Assembly:定义和加载程序集。
-
Module:模块信息(如包含模块的程序集和模块中的类)。
-
ConstructorInfo:构造函数信息(如名称、参数、访问修饰符等)。
-
MethodInfo:方法成员信息(如名称、返回类型、参数和访问修饰符等)。
-
FieldInfo:字段成员信息(如名称、访问修饰符)。
-
EventInfo:事件成员信息(如名称、事件处理程序的数据类型、自定义特性、声明类型以及事件的反射的类型)。
-
PropertyInfo:属性成员信息(如名称、数据类型、声明类型,反射的类型和属性的只读或可写状态),并获取或设置属性值。
-
ParameterInfo:参数成员信息(如参数名、数据类型以及参数在方法签名中的位置等)。
-
CustomAttributeData:自定义特性信息。
System.Reflection.Emit 命名空间的类提供一种专用形式的反射,使你能够在运行时生成类型。
反射的简单用法
命名空间:System.Reflection、System.Type、System.Reflection.Assembly
常见的获取 Type 对象的用法:
Type type1 = typeof(string); string msg = ""; Type type2 = msg.GetType();
一个常见的示例用法
我们一开始学习三层架构的时候,都应该会自己跟着老师动手打造一个 SqlHelper 的吧,这里我截取一个通过反射读取数据库数据并填充到一个对象的属性上,通过循环遍历,最后生成一个 list 列表的代码。
/// <summary> /// 执行 Reader 并读取数据转换成集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="sql"></param> /// <param name="commandType"></param> /// <param name="parameters"></param> /// <returns></returns> public static IList<T> ExecuteReaderToList<T>(string sql, CommandType commandType = CommandType.Text, params SqlParameter[] parameters) where T : new() { var type = typeof(T); var props = type.GetProperties(); var list = new List<T>(); using (var reader = ExecuteDataReader(sql, commandType, parameters)) { while (reader.Read()) { var entity = new T(); foreach (var propertyInfo in props) { var schemaTable = reader.GetSchemaTable(); if (schemaTable == null) return new List<T>(); schemaTable.DefaultView.RowFilter = $"ColumnName='{propertyInfo.Name}'"; if (schemaTable.DefaultView.Count <= 0) continue; if (!propertyInfo.CanWrite) continue; var val = reader[propertyInfo.Name]; if (val != DBNull.Value) propertyInfo.SetValue(entity, val); } list.Add(entity); } } return list; }
简单分析使用反射的代码:
(1)type.GetProperties():获取属性集合;
(2)propertyInfo.CanWrite:可写属性;
(3)propertyInfo.SetValue(entity, val):属性赋值,选择对应的对象进行赋值。