什么是反射?
反射就是动态发现类型信息的能力。它帮助程序设计人员在程序运行时利用一些信息去动态地使用类型,这些信息在设计时是未知的,这种能力类似于后期绑定。反射还支持的更高级的行为,能在运行时动态创建新类型,并且对这些新类型的操作进行调用。
听起来可能不太清楚,那反射有什么用呢?
- 在程序运行时,动态加载需要的程序集,以便操作其元数据。(例如有些IOC容器的实现,就是通过配置对应程序集,在运行时动态加载这些程序集,实现注入)
- 构造出可重用性的代码,通过反射可以动态的绑定/获取数据(例如orm中将查询结果转成实体,在更新数据时需要获取实体信息构造更新语句)
可能还是不太清楚,那下面就通过一个简单的例子来介绍一下:
自定义一个类和特性:
[AttributeUsage(AttributeTargets.Method)]
public class ApiAttribute : Attribute
{
public string name;
public ApiAttribute(string _name)
{
name = _name;
}
}
public class lwpoor
{
private int password;
public string name;
public lwpoor()
{
}
public lwpoor(string name)
{
this.name = name;
}
[Api("测试 test")]
public string test(string username)
{
return username;
}
public string test1(string username)
{
return username;
}
}
使用反射调用自定义类:
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
var type = typeof(lwpoor);
//获取所有公共属性
var pro = type.GetFields();
foreach (var prop in pro)
{
Console.WriteLine($"属性名称:{prop.Name} 类型:{prop.FieldType.Name}");
}
//获取类中标注ApiAttribute特性的方法
var methods = type.GetMethods()
.Where(p=>p.IsDefined(typeof(ApiAttribute),true)).ToList();
foreach (var method in methods)
{
ApiAttribute? att = method.GetCustomAttribute(typeof(ApiAttribute)) as ApiAttribute;
Console.WriteLine($"方法名:{method.Name} 说明:{att?.name}");
//获取方法所有参数
var parameters = method.GetParameters();
foreach (var param in parameters)
{
Console.WriteLine($"参数名:{param.Name} 参数类型:{param.ParameterType.Name}");
}
//创建实例
var obj = Activator.CreateInstance(type);
var key = Console.ReadLine();
//调用方法
var res = method.Invoke(obj, new object[] { key });
//获取方法返回类型
var aa = method.ReturnType.Name;
Console.WriteLine($"调用方法返回类型:{aa} 返回结果:{res}");
}
}
下面来做个总结:
反射提供封装程序集、模块和类型的对象。 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。 然后,可以调用类型的方法或访问其字段和属性。 反射的典型用法如下所示:
-
使用 Assembly 来定义和加载程序集,加载程序集清单中列出的模块,以及在此程序集中定位一个类型并创建一个它的实例。
-
使用 Module 发现信息,如包含模块的程序集和模块中的类。 还可以获取所有全局方法或模块上定义的其它特定的非全局方法。
-
使用 ConstructorInfo 发现信息,如名称、参数、访问修饰符(如
public
或private
)和构造函数的实现详细信息(如abstract
或virtual
)。 使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定构造函数。 -
使用 MethodInfo 发现信息,如名称、返回类型、参数、访问修饰符(如
public
或private
)和方法的实现详细信息(如abstract
或virtual
)。 使用 Type 的 GetMethods 或 GetMethod 方法来调用特定方法。 -
使用 FieldInfo 发现信息,如名称、访问修饰符(如
public
或private
)和一个字段的实现详细信息 (如static
);并获取或设置字段值。 -
使用 EventInfo 发现信息(如名称、事件处理程序的数据类型、自定义特性、声明类型以及事件的反射的类型),并添加或删除事件处理程序。
-
使用 PropertyInfo 发现信息(如名称、数据类型、声明类型,反射的类型和属性的只读或可写状态),并获取或设置属性值。
-
使用 ParameterInfo 发现信息,如参数的名称、数据类型、参数是输入参数还是输出参数以及参数在方法签名中的位置。
-
使用 CustomAttributeData 在于应用程序域的仅反射上下文中工作时发现有关自定义特性的信息。 CustomAttributeData 使你能够检查特性,而无需创建它们的实例。 System.Reflection.Emit 命名空间的类提供一种专用形式的反射,使你能够在运行时生成类型。