一、反射的定义与使用场景
反射是指程序可以访问、检测和修改它本身状态或行为的一种能力。程序集包含模块,而模块包含类型,类型包含成员。反射提供了封装程序集、模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了特性,可以利用反射对它们进行访问。
使用场景:
- 需要访问程序元数据的特性。
- 检查和实例化程序集中的类型。
- 在运行时构建新类型。使用System.Reflection.Emit中的类。
- 执行后期绑定,访问在运行时创建的类型的方法。
反射是.NET中重要的机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。
二、反射的用途
(1)使用Assembly定义和加载程序集,加载在程序集中的所有模块以及从此程序集中查找类型并创建该类型的实例。
(2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(5)使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
(8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
三、示例
1、使用Activator创建实例对象,有两种方式
using System;
using System.Reflection;
using System.Text;
namespace 反射的测试
{
public class SomeType
{
public void DoSomething(int x)
{
Console.WriteLine("100 / {0} = {1}", x, 100 / x);
}
}
class Program
{
static void Main(string[] args)
{
Object o = Activator.CreateInstance(typeof(SomeType));
SomeType sb = (SomeType)o;
sb.DoSomething(20);
// Create an instance of the SomeType class that is defined in this
// assembly.
Console.WriteLine("CodeBase = {0}", Assembly.GetEntryAssembly().CodeBase);
//"file:///F:/CodeTest/WpfApp1/反射的测试/bin/Debug/反射的测试.exe"
System.Runtime.Remoting.ObjectHandle oh =
Activator.CreateInstanceFrom(Assembly.GetEntryAssembly().CodeBase,
typeof(SomeType).FullName);
SomeType st = (SomeType)oh.Unwrap();
st.DoSomething(5);
Console.ReadKey();
}
}
}
2、用构造函数动态生成对象
Type t = typeof(RefClass);
Type[] pt = new Type[2];
pt[0]=typeof(string);
pt[1]=typeof(string);
//根据参数类型获取构造函数
ConstructorInfo ci = t.GetConstructor(pt);
//构造Object数组,作为构造函数的输入参数
object[] obj = new object[2] {"zhangsan","23"};
//调用构造函数生成对象
object o = ci.Invoke(obj);
//调用生成的对象的方法测试是否对象生成成功
((RefClass)o).Show();
3、通过程序集获取类对象
Assembly assembly = Assembly.Load("ReflectionDemo2");
Type t = assembly.GetType("ReflectionDemo2.ReflectionClass"); //参数必须是类的全名
object o = Activator.CreateInstance(t,"男");
MethodInfo mi = t.GetMethod("Show");
mi.Invoke(o,null);
4、获取类的字段,public,private,protect
static void Main(string[] args)
{
Type t = typeof(RefClass);
RefClass rc = new RefClass();
rc.Test3 = 3;
FieldInfo[] finfos = t.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (FieldInfo finfo in finfos)
{
Console.WriteLine("字段名称:{0} 字段类型:{1} rc中的值为:{2}", finfo.Name, finfo.FieldType.ToString(), finfo.GetValue(rc));
}
Console.ReadKey();
}
参考:
https://blog.csdn.net/Gnd15732625435/article/details/78587483?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1
https://www.cnblogs.com/yaozhenfa/p/CSharp_Reflection_1.html