[C#反射]C#中的反射解析及使用.

1、对C#反射机制的理解 2、概念理解后,必须找到方法去完成,给出管理的主要语法 3、最终给出实用的例子,反射出来dll中的方法

参考: C#反射,MSDN编程指南

反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等程序集内部的信息。使用反射可以看到一个程序集内部的接口、类、方法、字段、属性、特性等等信息。在System.Reflection命名空间内包含多个反射常用的类,下面表格列出了常用的几个类。 类型 作用  Assembly        通过此类可以加载操纵一个程序集,并获取程序集内部信息  EventInfo        该类保存给定的事件信息  FieldInfo         该类保存给定的字段信息  MethodInfo      该类保存给定的方法信息  MemberInfo     该类是一个基类,它定义了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多个公用行为  Module            该类可以使你能访问多个程序集中的给定模块  ParameterInfo 该类保存给定的参数信息        PropertyInfo    该类保存给定的属性信息

一、System.Reflection.Assembly类      通过Assembly可以动态加载程序集,并查看程序集的内部信息,其中最常用的就是Load()这个方法。      Assembly assembly=Assembly.Load("MyAssembly");      利用Assembly的object CreateInstance(string) 方法可以反射创建一个对象,参数0为类名。 二、System.Type类 Type是最常用到的类,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。一般有三个常用的方法可得到Type对象。 利用typeof() 得到Type对象

Type type=typeof(Example);

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

Example example=new Example();
Type type=example.GetType();

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

Type type=Type.GetType("MyAssembly.Example",false,true);

注意参数0是类名,参数1表示若找不到对应类时是否抛出异常,参数1表示类名是否区分大小写    例子:    我们最常见的是利用反射与Activator结合来创建对象。

Assembly assembly= Assembly.Load("MyAssembly");
Type type=assembly.GetType("Example");
object obj=Activator.CreateInstance(type);

三、反射方法    1.通过 System.Reflection.MethodInfo能查找到类里面的方法

1 Type type=typeof(Example);
2 MethodInfo[] listMethodInfo=type.GetMethods();
3 foreach(MethodInfo methodInfo in listMethodInfo)
4 Cosole.WriteLine("Method name is "+methodInfo.Name);

2.我们也能通过反射方法执行类里面的方法2.我们也能通过反射方法执行类里面的方法

1 Assembly assembly= Assembly.Load("MyAssembly");
2 Type type=assembly.GetType("Example");
3 object obj=Activator.CreateInstance(type);
4 MethodInfo methodInfo=type.GetMethod("Hello World");  //根据方法名获取MethodInfo对象
5 methodInfo.Invoke(obj,null);  //参数1类型为object[],代表Hello World方法的对应参数,输入值为null代表没有参数

四、反射属性 1.通过 System.Reflection.PropertyInfo 能查找到类里面的属性    常用的方法有GetValue(object,object[]) 获取属性值和 SetValue(object,object,object[]) 设置属性值

1 Type type=typeof(Example);
2 PropertyInfo[] listPropertyInfo=type.GetProperties();
3 foreach(PropertyInfo propertyInfo in listPropertyInfo)
4 Cosole.WriteLine("Property name is "+ propertyInfo.Name);

2.我们也可以通过以下方法设置或者获取一个对象的属性值2.我们也可以通过以下方法设置或者获取一个对象的属性值

1 Assembly assembly=Assembly.Load("MyAssembly");
2 Type type=assembly.GetType("Example");
3 object obj=Activator.CreateInstance(type);
4 PropertyInfo propertyInfo=obj.GetProperty("Name");    //获取Name属性对象
5 var name=propertyInfo.GetValue(obj,null);                //获取Name属性的值
6 PropertyInfo propertyInfo2=obj.GetProperty("Age");     //获取Age属性对象
7 propertyInfo.SetValue(obj,34,null);                              //把Age属性设置为34

五、反射字段     通过 System.Reflection.FieldInfo 能查找到类里面的字段     它包括有两个常用方法SetValue(object ,object )和GetValue(object)  因为使用方法与反射属性非常相似,在此不再多作介绍 六、反射特性    通过System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一个类里面的特性,以下例子可以反射出一个类的所有特性

1 Type type=typeof("Example");
2 object[] typeAttributes=type.GetCustomAttributes(false);       //获取Example类的特性
3 foreach(object attribute in typeAttributes)
4 Console.WriteLine("Attributes description is "+attribute.ToString());

通过下面例子,可以获取Example类Name属性的所有特性通过下面例子,可以获取Example类Name属性的所有特性

 1 public class Example
 2 {
 3     [DataMemberAttribute]
 4     publics string Name
 5     {get;set;}
 6     ..................
 7 }
 8 
 9 Type type = typeof(Example);        
10 PropertyInfo propertyInfo=type.GetProperty("Name");    //获取Example类的Name属性
11 foreach (object attribute in propertyInfo.GetCustomAttributes(false))        //遍历Name属性的所有特性
12     Console.WriteLine(“Property attribute: "+attribute.ToString());

总结:

Assembly.Load()方法,Assembly.LoadFrom()方法,Assembly.LoadFile()方法的区别 在C#中,我们要使用反射,首先要搞清楚以下命名空间中几个类的关系:     System.Reflection命名空间     (1)   AppDomain:应用程序域,可以将其理解为一组程序集的逻辑容器     (2)   Assembly:程序集类     (3)   Module:模块类     (4)   Type:使用反射得到类型信息的最核心的类     他们之间是一种从属关系,也就是说,一个AppDomain可以包含N个Assembly,一个Assembly可以包含N个Module,而一个Module可以包含N个Type.

1,Assembly.Load()     这个方法通过程序集的长名称(包括程序集名,版本信息,语言文化,公钥标记)来加载程序集的,会加载此程序集引用的其他程序集,一般情况下都应该优先使用 这个方法,他的执行效率比LoadFrom要高很多,而且不会造成重复加载的问题(原因在第2点上说明)     使用这个方法的时候, CLR会应用一定的策略来查找程序集,实际上CLR按如下的顺序来定位程序集:     ⑴如果程序集有强名称,在首先在全局程序集缓(GAC)中查找程序集。     ⑵如果程序集的强名称没有正确指定或GAC中找不到,那么通过配置文件中的<codebase>元素指定的URL来查找     ⑶如果没有指定强名称或是在GAC中找不到,CLR会探测特定的文件夹:     假设你的应用程序目录是C:\AppDir,<probing>元素中的privatePath指定了一个路径Path1,你要定位的程序集是AssemblyName.dll则CLR将按照如下顺序定位程序集     C:\AppDir\AssemblyName.dll     C:\AppDir\AssemblyName\AssemblyName.dll     C:\AppDir\Path1\AssemblyName.dll     C:\AppDir\Path1\AssemblyName\AssemblyName.dll     如果以上方法不能找到程序集,会发生编译错误,如果是动态加载程序集,会在运行时抛出异常! 2,Assembly.LoadFrom()     这个方法从指定的路径来加载程序集,实际上这个方法被调用的时候,CLR会打开这个文件,获取其中的程序集版本,语言文化,公钥标记等信息,把他们传递给 Load方法,接着,Load方法采用上面的策略来查找程序集。如果找到了程序集,会和LoadFrom方法中指定的路径做比较,如果路径相同,该程序集 会被认为是应用程序的一部分,如果路径不同或Load方法没有找到程序集,那该程序集只是被作为一个"数据文件"来加载,不会被认为是应用程序的一部分。 这就是在第1点中提到的Load方法比LoadFrom方法的执行效率高的原因。另外,由于可能把程序集作为"数据文件"来加载,所以使用 LoadFrom从不同路径加载相同程序集的时候会导致重复加载。当然这个方法会加载此程序集引用的其他程序集。 3,Assembly.LoadFile()     这个方法是从指定的文件来加载程序集,和上面方法的不同之处是这个方法不会加载此程序集引用的其他程序集!     结论:一般大家应该优先选择Load方法来加载程序集,如果遇到需要使用LoadFrom方法的时候,最好改变设计而用Load方法来代替!     另:Assembly.LoadFile 与 Assembly.LoadFrom的区别     1、Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("abc.dll"),则载入abc.dll,假如abc.dll中引用了def.dll的话,def.dll并不会被载入。     Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,def.dll也会被载入。     2、用Assembly.LoadFrom载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,比如abc.dll有两个版本(版本1在目录1下,版本2放在目录2下),程序一开始时载入了版本1,当使用Assembly.LoadFrom("2\\abc.dll")载入版本2时,不能载入,而是返回版本1.Assembly.LoadFile的话则不会做这样的检查,比如上面的例子换成Assembly.LoadFile的话,则能正确载入版本2.     LoadFile:加载指定路径上的程序集文件的内容。LoadFrom: 根据程序集的文件名加载程序集文件的内容。     区别:     LoadFile 方法用来来加载和检查具有相同标识但位于不同路径中的程序集。但不会加载程序的依赖项。     LoadFrom 不能用于加载标识相同但路径不同的程序集。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏光变

Redis持久化文件RDB的格式解析

Redis的RDB文件是对内存存储的一种表示。这个二进制文件足以完全恢复Redis当时的运行状态。 RDB文件格式针对快速读写进行了优化。LZF压缩被用于减小文...

15910
来自专栏老付的网络博客

详解.net中IL语言

中间语言,又称(IL语言)。充当Clr与.net 平台的中间语言,比如用C#编写程序,编译器首先是把C#代码转译成IL语言,最终由Clr解释执行,下面我们学习下...

17920
来自专栏大内老A

ASP.NET MVC涉及到的5个同步与异步,你是否傻傻分不清楚?[下篇]

关于ASP.NET MVC对请求的处理方式(同步或者异步)涉及到的五个组件,在《上篇》中我们谈了三个(MvcHandler、Controller和ActionI...

21260
来自专栏GreenLeaves

C#多线程学习一

一、概述:C#支持多线程并行执行程序,一个线程有他单独的执行路径,能够与其他线程同时执行,一个程序是由一个单线程开始,该单线程由CLR(公共语言运行时)和操作系...

28970
来自专栏丑胖侠

《Drools7.0.0.Final规则引擎教程》第4章 Function函数

Function函数 首先来看一下function函数的语法结构图: ? 函数是将语义代码放置在规则文件中的一种方式,就相当于java类中的方法一样。函数...

23180
来自专栏熊二哥

快速入门系列--深入理解C#

C#语言在近些年得到了长足的方法,代码风格越来越简洁美观,例如常用的泛型及其约束、可空类型、隐式类型、匿名类型和委托等,通过下面的表格可以对这部分相对简单的特性...

20650
来自专栏技术专栏

慕课网Flask构建可扩展的RESTful API-4. 理解WTForms并灵活改造她

之前的代码,修改完成之后,已经修复了之前的缺陷,但是这样爆出了两个问题: 1.代码太啰嗦了,每个试图函数里,都需要这么写 2.ClientTypeError...

12910
来自专栏Petrichor的专栏

python: json库 & .json文件读写

[1] python读写json文件 [2] 使用 python 读写中文json

22320
来自专栏大内老A

ModelBinder——ASP.NET MVC Model绑定的核心

Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数。通过前面的介绍我们知道Action方法的参数通过ParameterDescrip...

24390
来自专栏Redis源码学习系列

Redis源码学习之字符串对象

前文中提到,Redis的字符串对象的底层数据结构有三种,分别是整数编码、EMBSTR编码和SDS编码。在不同使用场景下进行相互切换,起到节约内存的作用。

29030

扫码关注云+社区

领取腾讯云代金券