HI END


一种永不妥协,追求极致与完美的精神与态度。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

理解反射(Reflection)(上) (转 )

Posted on 2013-05-10 10:40  HI END  阅读(279)  评论(0编辑  收藏  举报

来源:http://www.cnblogs.com/yeanzhi/archive/2013/05/08/3067865.html

"反射"是.NET中的重要技术,通过反射,可以在运行时获得某个类型的各种信息,进而动态的创建对象实例,完成方法调用,属性设置和事件激发。在.NET中“代码特性(Attribute)”就利用了反射技术。

反射技术的基础

反射的特点:允许一个对象的类型带程序运行时才确定。

反射作用:这个技术在实际开发中很有用,它使我们可以动态的替换掉系统中的某一部分而不用重新编译源码。

反射概述

反射的基本作用:运行期,根据对象名就能获得该对象的:类型方法属性,还可以获得每个成员的名称,访问权限和参数信息,这些信息都存储于元数据中,因此反射处理的对象是程序集元数据。

注:著名的Reflector软件就是利用反射技术编写的,可以查看.NET程序集中的所有数据类型,并反编译为C#等语言的源代码。

.NET程序集的层次结构

C#程序中声明的“类型”包含成员,比如类中就包含方法,属性,字段等成员,并且按照命名空间进行组织,类就是类型(Type)的示例。在编译程序的时候被打包为程序集(通常拓展名为exe或dll,前者可直接执行,后者必须加载到进程中才能被执行)。

在System.Reflection命名空间内包含多个反射常用的类,下面表格列出了常用的几个类。

类型         作用
Assembly      通过此类可以加载操纵一个程序集,并获取程序集内部信息
EventInfo      该类保存给定的事件信息
FieldInfo        该类保存给定的字段信息
MethodInfo      该类保存给定的方法信息
MemberInfo     该类是一个基类,它定义了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多个公用行为
Module        该类可以使你能访问多个程序集中的给定模块
ParameterInfo     该类保存给定的参数信息      
PropertyInfo      该类保存给定的属性信息

上述的信息被存放在模块的源数据中,使用System.Type类代表抽象的数据类型,我们可以使用顶层的Object类提供的GetType()方法来获得它所对应的Type对象。

数据类型的奥秘System.Type类

 

Type类是一个特殊的数据类型,他是可以表达数据类型信息的数据类型。参照下面的代码理解

复制代码
public class cla1
{
     public int i;
     public void met(){}
     public string pro{get;set;}
}
复制代码

上诉代码定义了一个public类型的cla1,拥有以下类型

1)类名cla1,公有,

2)父类为Object类

3)公有字段 i

4)公有方法 met()

5)公有属性 pro

上述的信息都被封装到了Type类型的对象中。Type是最常用到的类,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。一般有三个常用的方法可以得到Type对象。

1.利用typeof()得到Type对象

 

cla1 c1= new cla1(); 
Type type = typeof(cla1);

 

2.利用System.Object.GetType()得到Type对象

 

  cla1 c1= new cla1();
  Type type = c1.GetType();

 

3.利用System.Type.GetType()得到Type对象

 

Type type = Type.GetType("MyAssembly.cla1",false,true)   //注意0是类名,参数1表示若找不到对应类时是否抛出异常,参数2表示类名是否区分大小写

 

三者的区别在于:

typeof()和Type.GetType()是从一个类中获取对象,而Object.GetType()是从一个类的实例获得对象。

 

而前两者的区别在于

 

  • Typeof()是运算符而GetType是方法
  • GetType()是基类System.Object的方法,因此只有建立一个实例之后才能够被调用(初始化以后)
  • Typeof()的参数只能是int,string,String,自定义类型,且不能是实例
  • GetType() 和typeof()都返回System.Type的引用。

动态对象的创建与方法的调用

读者读到这里 的时候一定会问,我知道这些信息能做什么,其实 一旦你拿到这些Type对象的信息就可以在需要的时候创建这一类型的对象,并且调用它的方法,并且保存此类型的Assembly文件,并不需要添加程序集引用。

动态对象创建

Assembly类有一个CreateInstance方法,用于创建对象,其定义为

public Object CreateInstance(string typename);

只要传给这个方法一个类型名称的字符串就可以创建一个对象。

复制代码
复制代码
    class Program
    {
        static void Main(string[] args)
        {
            Assembly assm = Assembly.Load("fanshe");
            Console.WriteLine(assm.FullName);   //输出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

            //注释上面两行,移除程序集的引用

            Assembly assm1 = Assembly.LoadFrom(@"D:\fanshe.dll");
            Console.WriteLine(assm1.FullName);      ////输出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

            //与Assembly.LoadFrom基本一样,只是如果被加载的dll,还依赖其他的dll的话,它不会加载
            Assembly assm2 = Assembly.LoadFile(@"D:\fanshe.dll");
            Console.WriteLine(assm2.FullName);

            Console.ReadKey();
        }
    }
复制代码
复制代码