反射是:指程序可以访问、检测和修改它本身状态或行为的一种能力
反射是一种能力,所以给的定义就是说明了它能干嘛。
我们平时用反射主要做:
获取类型的相关信息反射的核心Type类,Type对象提供的属性和方法可以获取对象的一切信息,如:方法、字段、属性、事件...等等。
我们获取已加载程序集中类型的Type对象的几种方法:(以StringBuilder 类型为例)
不管使用那种,我们最终得到的结果都是一样的。
那么我们通过Type又能得到些什么信息呢?
获取类型本身信息(命名空间名、全名、是否是抽象、是否是类、、、等等)var T1 = typeof(StringBuilder); Console.WriteLine(+ T1.Namespace); Console.WriteLine(+ T1.BaseType); Console.WriteLine(+ T1.FullName); Console.WriteLine(+ T1.IsAbstract); Console.WriteLine(+ T1.IsClass); //.....等等
获取类型成员信息(通过Tyep中的方法GetMembers)
Type T1 = typeof(TClass); (var m in Mets) { Console.WriteLine(+ m.MemberType.ToString()+ + m.Name); // m.MemberType 是成员类型 }
MemberType所能包含的成员类型有哪些呢?如:(可以自己可以F12进去看看)
注意:其中MemberInfo的属性DeclaringType返回的是这个属性定义的类型,而ReflectedType返回的是获取这个属性的对象类型。
如:
Type T2 = typeof(TClass);
var Mets = T2.GetMembers();//获取所有公共成员(返回值是MemberInfo类型集合)
foreach (var m in Mets)
{
)
{
Console.WriteLine(+ m.MemberType.ToString() + + m.Name);
// m.MemberType 是成员类型
// m.DeclaringType;//获取申明该成员的类
// m.ReflectedType;//获取用于获取 MemberInfo 的此实例的类对象。
}
}
T2中的Equals,我们知道这个方式是在Objec中定义的,在TClass中调用的,所以:
我们发现获取Type对象的成员大多都是以 isxxx、Getxxx、Getxxxs格式的。
isxxx格式的基本上都是判断是否是某类型。
Getxxx和Getxxxs都是放回某类型和某类型集合。其中主要的类型有:
//FieldInfo封装了关于字段的所有信息 (通过Tyep对象的GetFields或GetField方法)
//PropertyInfo类型,封装了类型的属性信息;(通过Type对象的GetProperties或GetProperty方法)
//ConstructorInfo类型,封装了类型的构造函数信息; (..........)
//MethodInfo类型,封装了类型的方法信息; (........)
//MemberInfo类型,封装了类型的所有公共成员;(**就是我们上面说的GetMembers方法**)
//EventInfo类型,封装了类型的事件信息;(.......)
//ParameterInfo类型,封装了方法和构造函数的参数信息;(........)
它们都在 System.Reflection 命名空间下,其每个isxxx、Getxxx、Getxxxs的细节实例用法就不一一演示了。和上面的GetMembers用法区别不大。
动态调用方法首先定义个类:
public class TClass { public void fun(string str) { Console.WriteLine(+ str); } public void fun2() { Console.WriteLine(); } fun3() { Console.WriteLine(); } }
调用方式一(使用InvokeMember调用方法)调用带参实例方法fun
Type T1 = typeof(TClass); T1.InvokeMember(, BindingFlags.InvokeMethod, });
调用无参实例方法fun2
Type T1 = typeof(TClass); T1.InvokeMember(, BindingFlags.InvokeMethod, null, new TClass(), null);
调用静态方法
Type T1 = typeof(TClass); T1.InvokeMember(, BindingFlags.InvokeMethod, null, T1, null);
我们发现了一个问题当我们调用实例方法的时候需要传实例对象过去。(有人会说,都实例对象了,我还要你动态掉调用个屁啊。有种情况,在我们实例了对象后,仍不确定应该调用那个方法时可以只有使用。然后有人有说了,那如果实例对象我也不确定呢?那我们下面会分析连实例对象也给动态了。那接着完下看吧。)
我们来说下这几个参数的意思吧。
第一个:要被动态调用的方法名。
第二个:是一个枚举,表示是调用一个方法
第三个:是Binder,传的是null,使用默认值。
第四个:传如实例对象(调用实例方法时)或者Type对象(调用静态方法时)。
第五个:要传给被调用发的参数数组。
调用方式二(使用MethodInfo.Invoke调用方法)