简述:
反射指程序可以访问、检测和修改它本身状态或行为的一种能力。
程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。
您可以使用使用反射获取类型,根据类型来动态创建对象,可以获取方法以及动态调用方法,可以动态创建委托。然后,可以调用类型的方法或访问其字段和属性。
 扩展:
 如何使用反射获取类型
 首先我们来看如何获得类型信息。
 获得类型信息有两种方法,一种是得到实例对象
 这个时侯我仅仅是得到这个实例对象,得到的方式也许是一个object的引用,也许是一个接口的引用,但是我并不知道它的确切类型,我需要了解,那么就可以通过调用System.Object上声明的方法GetType来获取实例对象的类型对象,比如在某个方法内,我需要判断传递进来的参数是否实现了某个接口,如果实现了,则调用该接口的一个方法:
public  void  Process(  object  processObj  )
{
Type  t  =  processsObj.GetType();
if(  t.GetInterface(“ITest”)  !=null  )…
}
另外一种获取类型的方法是通过Type.GetType以及Assembly.GetType方法,如:
 Type t = Type.GetType(“System.String”);
 需要注意的是,前面我们讲到了命名空间和装配件的关系,要查找一个类,必须指定它所在的装配件,或者在已经获得的Assembly实例上面调用GetType。
如何根据类型来动态创建对象
 System.Activator提供了方法来根据类型动态创建对象,比如创建一个DataTable:
Type  t  =  Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,  Culture=neutral,  PublicKeyToken=b77a5c561934e089");
DataTable  table  =  (DataTable)Activator.CreateInstance(t);
例二:根据有参数的构造器创建对象
namespace  TestSpace  
{public  class  TestClass{private  string  _value;public  TestClass(string  value)  {_value=value;}}
}
…
Type  t  =  Type.GetType(“TestSpace.TestClass”);
Object[]  constructParms  =  new  object[]  {“hello”};  //构造器参数
TestClass  obj  =  (TestClass)Activator.CreateInstance(t,constructParms);
…
把参数按照顺序放入一个Object数组中即可
 如何获取方法以及动态调用方法
namespace  TestSpace
{public  class  TestClass  {private  string  _value;public  TestClass()  {}public  TestClass(string  value)  {_value  =  value;}public  string  GetValue(  string  prefix  )  {if(  _value==null  )return  "NULL";elsereturn  prefix+"  :  "+_value;}public  string  Value  {
set  {
_value=value;
}
get  {
if(  _value==null  )
return  "NULL";
else
return  _value;
}}}
}
上面是一个简单的类,包含一个有参数的构造器,一个GetValue的方法,一个Value属性,我们可以通过方法的名称来得到方法并且调用之,如:
//获取类型信息
Type  t  =  Type.GetType("TestSpace.TestClass");
//构造器的参数
object[]  constuctParms  =  new  object[]{"timmy"};
//根据类型创建对象
object  dObj  =  Activator.CreateInstance(t,constuctParms);
//获取方法的信息
MethodInfo  method  =  t.GetMethod("GetValue");
//调用方法的一些标志位,这里的含义是Public并且是实例方法,这也是默认的值
BindingFlags  flag  =  BindingFlags.Public  |  BindingFlags.Instance;
//GetValue方法的参数
object[]  parameters  =  new  object[]{"Hello"};
//调用方法,用一个object接收返回值
object  returnValue  =  method.Invoke(dObj,flag,Type.DefaultBinder,parameters,null);
动态创建委托
 委托是C#中实现事件的基础,有时候不可避免的要动态的创建委托,实际上委托也是一种类型:System.Delegate,所有的委托都是从这个类派生的
 System.Delegate提供了一些静态方法来动态创建一个委托,比如一个委托:
namespace  TestSpace  {delegate  string  TestDelegate(string  value);public  class  TestClass  {
public  TestClass()  {}public  void  GetValue(string  value)  {return  value;}}
}
使用示例:
TestClass  obj  =  new  TestClass();
//获取类型,实际上这里也可以直接用typeof来获取类型
Type  t  =  Type.GetType(“TestSpace.TestClass”);
//创建代理,传入类型、创建代理的对象以及方法名称
TestDelegate  method  =  (TestDelegate)Delegate.CreateDelegate(t,obj,”GetValue”);
String  returnValue  =  method(“hello”);
优缺点
 优点:
1、反射提高了程序的灵活性和扩展性。
2、降低耦合性,提高自适应能力。
3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
缺点:
1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。