反射是一种机制,通过这种机制我们可以知道一个未知类型的类型信息.比如,有一个对象a,这个对象不是我们定义的,也许是通过网络捕捉到的,也许是使用泛型定义的,但我们想知道这个对象的类型信息,想知道这个对象有哪些方法或者属性什么的.甚至我们想进一步调用这个对象的方法.关键是现在我们只知道它是一个对象,不知道它的类型,自然不会知道它有哪些方法等信息.这时我们该怎么办?反射机制就是解决这么一个问题的.通过反射机制我们可以知道未知类型对象的类型信息.
再比如,我们有一个dll文件,我们想调用里面的类.现在假设这个dll文件的类的定义,数量等不是固定的,是经常变化的.也许某一天你要在这个dll里面增加一个类定义.也许你觉得这没什么问题,现在关键是我们在另一个程序集里面要调用这个dll,这是我们的程序必须能够适应这个dll的变化,也就是说即使改变了dll文件的定义也不需要改变我们的程序集.这时候我们就会使用一个未知dll.我们该怎么办?同样,反射机制帮助了我们,我们可以通过反射来实现.
下面我举一个例子说明:
首先我新建一个控制台应用程序,然后添加一个类库Model,在类库中添加一个类People.cs如下:
namespace Model { public class People { public string name { get; set; } public string sex { get; set; } public int age { get; set; } public string GetName() { return "我的名字是" + name; } public string Display() { return "我的名字是:" + name + "\n我的性别是:" + sex + "\n我的年龄:" + age+"\n"; } public People(string name,string sex,int age) { this.name = name; this.sex = sex; this.age = age; } } }
然后在main函数中些如下代码:
static void Main(string[] args) { var asssembly = Assembly.Load("Model");//加载程序集 Console.WriteLine("程序集名称:{0}", asssembly.FullName); Console.WriteLine(); Type people = asssembly.GetType("Model.People");//获取类型信息,这里要写完整的名称 Object[] PeopleParms = new object[] {"袁安云","男",22}; //构造器参数,这就要求重载构造函数,如果我想这样写me.name="袁安云",多方便啊,
//不过这样的话,需要强制类型转换,如:var you=(Model.People)me,然后you.name="袁安云";
Object me = Activator.CreateInstance(people,PeopleParms);//根据类型创建对象 MethodInfo method = people.GetMethod("Display");//获取方法的信息 Console.WriteLine(method.Invoke(me, null));//调用方法,第二个参数为方法的参数,是一个object类型数组,不需要参数时设为null Console.ReadKey(); }
运行结果:
说明:
在VS.Net中,有很多种方法动态调用对象的构造函数。一是通过Activator类的CreateInstance()方法。这个方法我们在Remoting中也用过。它实际上是在本地或从远程创建对象类型,或获取对现有远程对象的引用。它的方法签名是:public static object CreateInstance(Type);(还有其他重载方法)注意它的返回值为object,MSDN对返回值的描述是:对新创建对象的引用。
二是通过Assembly类的方法CreateInstance()。方法名和前一样,不过它不是静态方法。Assembly是在System.Reflection命名空间中。方法签名:public object CreateInstance(Type);(同样还有其他重载方法)返回值仍然是object,MSDN对返回值的描述是:表示该类型的 Object 的实例,其区域性、参数、联编程序和激活属性设置为空引用(Visual Basic 中为 Nothing),并且 BindingFlags 设置为 Public 或 Instance,或者设置为空引用 (Nothing)(如果没有找到 typeName)。
当然还有其他方法,例如通过MethodInfo获得方法信息后,根据IsConstructor属性,判断是否构造函数,再根据GetParamters()方法获得参数,最后通过Invoke()方法来调用,等等……。大家可以参考MSDN。
问题:
以上调用方法Display是这样实现的:
MethodInfo method = people.GetMethod("Display");//获取方法的信息
Console.WriteLine(method.Invoke(me, null));//调用方法,第二个参数为方法的参数,是一个object类型数组,不需要参数时设为null
如果我想这样写me.Display(),该如果实现呢?采用强制类型转换即可:
var you = (Model.People) me;
Console.WriteLine(you.Display());