对“反射”的深入认识,你会发觉跟“解剖”一样
对很多人来说,对.Net的反射机制不甚了解,其实反射是一种很优秀的机制,知道了它,就可以把握很多程序的脉搏。如何这样说呢?首先,反射是这样定义的:可以在运行时根据所提供的类库(.dll)来进行解析以获得其中包含的类型(包含类、结构、委托、接口、枚举等)成员,进而获取到对应的方法、属性、事件以及构造函数等(甚至可获得对应的名称、限定符和参数)信息。有了这些信息,我们就可以动态的创建对象,即使在编译时不知道对象的类型也无所谓。打个比方:反射好比人体解剖,可以给一个完整的人(^^哈哈,当然是死人哈,这里类比一个.dll文件),通过解剖(反射)就可以获取对应的部位(成员),进而利用这些部位去做更多的事情(如利用DNA克隆)。是不是很神奇啊!下面我们以一个完整的例子来说明:
1. 首先建立一个类型库项目(Library),并添加一个类Person,生成一个类库程序集(Library.dll)。
namespace Library
{
public class Person
{
private string name;
private string sex;
private int age;
public Person() : this(null) { }
public Person(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Sex
{
get { return sex; }
set { sex = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public void Say()
{
if (name == null)
{
Console.WriteLine("Hello World");
}
else
{
Console.WriteLine("Hello " + name);
}
}
}
}
2. 再建立一个控制台(测试)项目Test,并将Library.dll拷贝到本项目的bin/debug目录下。特别注意的是,在此项目中必须添加System.Reflection。
using System.Reflection;
static void Main(string[] args)
{
Console.WriteLine("列出程序集Library.dll中的所有类型");
Assembly asm = Assembly.LoadFrom("Library.dll");
Type person = null;
Type[] types = asm.GetTypes();
foreach (Type t in types)
{
Console.WriteLine(t.Name);
if (t.Name == "Person")
{
person = t;
}
}
Console.WriteLine("列出类型Person的所有方法");
MethodInfo[] methods = person.GetMethods();
foreach (MethodInfo mi in methods)
{
Console.WriteLine(mi.Name);
}
Console.WriteLine("实例化类型Person并调用方法Say()");
object obj = Activator.CreateInstance(person);
object miracle = Activator.CreateInstance(person, "Miracle");
MethodInfo say = person.GetMethod("Say");
say.Invoke(obj, null);//输出Hello World
say.Invoke(miracle, null);//输出Hello Miracle
}
从以上两点就可以完整地看到反射的过程,类似于.NET的反编译机制(有兴趣的朋友可以去研究一下IDASM和Reflector工具)。