c#中reflection(反射)

上传人:wt****50 文档编号:32821435 上传时间:2018-02-12 格式:DOCX 页数:21 大小:98.79KB
返回 下载 相关 举报
c#中reflection(反射)_第1页
第1页 / 共21页
c#中reflection(反射)_第2页
第2页 / 共21页
c#中reflection(反射)_第3页
第3页 / 共21页
c#中reflection(反射)_第4页
第4页 / 共21页
c#中reflection(反射)_第5页
第5页 / 共21页
点击查看更多>>
资源描述

《c#中reflection(反射)》由会员分享,可在线阅读,更多相关《c#中reflection(反射)(21页珍藏版)》请在金锄头文库上搜索。

1、C#中 Reflection 反射反射(Reflection)是.NET 中的重要机制,通过放射,可以在运行时获得.NET 中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称、限定符和参数等。有了反射,即可对每一个类型了如指掌。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不知道。 程序代码在编译后生成可执行的应用,我们首先要了解这种可执行应用程序的结构。 应用程序结构分为应用程序域程序集模块类型成员几个层次,公共语言运行库加载器管理应用程序域,这种管理包括将每个程序集加载到相应的应用程序域以及控制每

2、个程序集中类型层次结构的内存布局。 程序集包含模块,而模块包含类型,类型又包含成员,反射则提供了封装程序集、模块和类型的对象。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或从现有对象中获取类型,然后调用类型的方法或访问其字段和属性。反射通常具有以下用途。 (1)使用 Assembly 定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。 (2)使用 Module 了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 (3)使用 ConstructorInfo 了解构造函数的名称、参数、访问修饰符(

3、如 pulic 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定的构造函数。 (4)使用 MethodInfo 了解方法的名称、返回类型、参数、访问修饰符(如 pulic 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法来调用特定的方法。 (5)使用 FiedInfo 了解字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如stat

4、ic)等,并获取或设置字段值。 (6)使用 EventInfo 了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。 (7)使用 PropertyInfo 了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。 (8)使用 ParameterInfo 了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。 System.Reflection.Emit 命名空间的类提供了一种特殊形式的反射,可以在运行时构造类型。 反射也可用于创建称为类型浏览器的应用程序,使用户能够选择类型,然后查看有关选定类型的信

5、息。此外,Jscript 等语言编译器使用反射来构造符号表。System.Runtime.Serialization 命名空间中的类使用反射来访问数据并确定要永久保存的字段,System.Runtime.Remoting 命名空间中的类通过序列化来间接地使用反射。2008 年 03 月 01 日 星期六 下午 07:36来源http:/ 什么是反射2、 命名空间与装配件的关系3、 运行期得到类型信息有什么用4、 如何使用反射获取类型5、 如何根据类型来动态创建对象6、 如何获取方法以及动态调用方法7、 动态创建委托1、什么是反射Reflection,中文翻译为反射。这是.Net 中获取运行时类

6、型信息的方式, .Net 的应用程序由几个部分:程序集(Assembly)、模块(Module)、类型 (class)组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,例如:Assembly 类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。Type 类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过 Type 类可以得到这些要素的信息,并且调用之。MethodInfo 包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。诸如此类,还有 FieldI

7、nfo、EventInfo 等等,这些类都包含在 System.Reflection 命名空间下。2、命名空间与装配件的关系很多人对这个概念可能还是很不清晰,对于合格的.Net 程序员,有必要对这点进行澄清。命名空间类似与 Java 的包,但又不完全等同,因为 Java 的包必须按照目录结构来放置,命名空间则不需要。 装配件是.Net 应用程序执行的最小单位,编译出来的.dll、.exe 都是装配件。装配件和命名空间的关系不是一一对应,也不互相包含,一个装配件里面可以有多个命名空间,一个命名空间也可以在多个装配件中存在,这样说可能有点模糊,举个例子:装配件 A:namespace N1publ

8、ic class AC1 public class AC2 namespace N2public class AC3 public class AC4装配件 B:namespace N1public class BC1 public class BC2 namespace N2public class BC3 public class BC4这两个装配件中都有 N1 和 N2 两个命名空间,而且各声明了两个类,这样是完全可以的,然后我们在一个应用程序中引用装配件 A,那么在这个应用程序中,我们能看到N1 下面的类为 AC1 和 AC2,N2 下面的类为 AC3 和 AC4。接着我们去掉对 A

9、的引用,加上对 B 的引用,那么我们在这个应用程序下能看到的N1 下面的类变成了 BC1 和 BC2,N2 下面也一样。如果我们同时引用这两个装配件,那么 N1 下面我们就能看到四个类:AC1、AC2 、BC1 和 BC2。到这里,我们可以清楚一个概念了,命名空间只是说明一个类型是那个族的,比如有人是汉族、有人是回族;而装配件表明一个类型住在哪里,比如有人住在北京、有人住在上海;那么北京有汉族人,也有回族人,上海有汉族人,也有回族人,这是不矛盾的。上面我们说了,装配件是一个类型居住的地方,那么在一个程序中要使用一个类,就必须告诉编译器这个类住在哪儿,编译器才能找到它,也就是说必须引用该装配件。

10、那么如果在编写程序的时候,也许不确定这个类在哪里,仅仅只是知道它的名称,就不能使用了吗?答案是可以,这就是反射了,就是在程序运行的时候提供该类型的地址,而去找到它。有兴趣的话,接着往下看吧。3、运行期得到类型信息有什么用有人也许疑问,既然在开发时就能够写好代码,干嘛还放到运行期去做,不光繁琐,而且效率也受影响。这就是个见仁见智的问题了,就跟早绑定和晚绑定一样,应用到不同的场合。有的人反对晚绑定,理由是损耗效率,但是很多人在享受虚函数带来的好处的时侯还没有意识到他已经用上了晚绑定。这个问题说开去,不是三言两语能讲清楚的,所以就点到为止了。我的看法是,晚绑定能够带来很多设计上的便利,合适的使用能够

11、大大提高程序的复用性和灵活性,但是任何东西都有两面性,使用的时侯,需要再三衡量。接着说,运行期得到类型信息到底有什么用呢?还是举个例子来说明,很多软件开发者喜欢在自己的软件中留下一些接口,其他人可以编写一些插件来扩充软件的功能,比如我有一个媒体播放器,我希望以后可以很方便的扩展识别的格式,那么我声明一个接口:public interface IMediaFormatstring Extension get;Decoder GetDecoder();这个接口中包含一个 Extension 属性,这个属性返回支持的扩展名,另一个方法返回一个解码器的对象(这里我假设了一个 Decoder 的类,这个

12、类提供把文件流解码的功能,扩展插件可以派生之),通过解码器对象我就可以解释文件流。那么我规定所有的解码插件都必须派生一个解码器,并且实现这个接口,在 GetDecoder方法中返回解码器对象,并且将其类型的名称配置到我的配置文件里面。这样的话,我就不需要在开发播放器的时侯知道将来扩展的格式的类型,只需要从配置文件中获取现在所有解码器的类型名称,而动态的创建媒体格式的对象,将其转换为IMediaFormat 接口来使用。这就是一个反射的典型应用。4、如何使用反射获取类型首先我们来看如何获得类型信息。获得类型信息有两种方法,一种是得到实例对象这个时侯我仅仅是得到这个实例对象,得到的方式也许是一个

13、object 的引用,也许是一个接口的引用,但是我并不知道它的确切类型,我需要了解,那么就可以通过调用System.Object 上声明的方法 GetType 来获取实例对象的类型对象,比如在某个方法内,我需要判断传递进来的参数是否实现了某个接口,如果实现了,则调用该接口的一个方法:public void Process( object processObj )Type t = processsObj.GetType();if( t.GetInterface(“ITest”) !=null )另外一种获取类型的方法是通过 Type.GetType 以及 Assembly.GetType 方法,

14、如:Type t = Type.GetType(“System.String”);需要注意的是,前面我们讲到了命名空间和装配件的关系,要查找一个类,必须指定它所在的装配件,或者在已经获得的 Assembly 实例上面调用 GetType。本装配件中类型可以只写类型名称,另一个例外是 mscorlib.dll,这个装配件中声明的类型也可以省略装配件名称(.Net 装配件编译的时候,默认都引用了 mscorlib.dll,除非在编译的时候明确指定不引用它),比如:System.String 是在 mscorlib.dll 中声明的,上面的 Type t = Type.GetType(“System

15、.String”)是正确的System.Data.DataTable 是在 System.Data.dll 中声明的,那么:Type.GetType(“System.Data.DataTable”)就只能得到空引用。必须:Type t = Type.GetType(System.Data.DataTable,System.Data,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089);这样才可以,大家可以看下面这个帖子:http:/ qqchen 的回答很精彩5、如何根据类型来动态创建对象System.Activator 提供了方法来根据类型动态创建对象,比如创建一个 DataTable:Type t = Type.GetType(System.Data.DataTable,System.Data,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089);DataTable

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 机械/制造/汽车 > 机械理论及资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号