以前总有人说”反射反射程序员的快乐“每次听到这句话心里总是对说这句话的人无比的钦佩,还记得那时我还是刚毕业,那么今天咱们深入了解一下反射到底是一个什么技术,什么原理,让程序员如此喜欢。
在编程当中可以说反射是无处不在的,比如封装框架,系统开发,MVC,IOC,ORM等等,
高级语言到计算机语言的历程
解释:
metadata:元数据清单 记录了dll中包含了那些东西是一个描述
IL:中间语言 编译器把高级语言编译后得到C#最真实的语言状态,面向对象语言
反射:来自于System.reflection ,是一个帮助类库可以读取到dll或者exe中的metadata和使用metadata+动态创建dll或者exe
我们先来了解介System. Type 类, 通过这个类可以访问关于任何数据类型的信息。 然后简要介绍System. Reflection. Assembly 类,它可以用于访问给定程序集的相关信息,或者把这个程序集加载到程序中。
反射读取dll文件的三种方式和注意事项,
LoadFrom,Load,LoadFile
1 loadfrom 是通过详细的文件地址和扩展名来加载dll文件的,同时程序集内部引用了其他程序集则也会一起加载进去
2 load 加载文件有两种方式一种是程序集信息或者(程序集的强名称)
3 loadfile 通过文件的详细地址 不会加载目标程序集所引用和依赖的其他程序集
静态成员Assembly.Load()或Assembly.LoadFrom()。这两个方法的区别是Load()方法的参数是程序集的名称,运行库会在各个位置上搜索该程序集,试图找到该程序集,这些位置包括本地目录和全局程序集缓存。而LoadFrom()方法的参数是程序集的完整路径名,它不会在其他位置搜索该程序集:
综上所述,一般动态加载dll文件时应优先选择load加加载程序集,同时需要格外注意程序集的版本是否跟读取dll文件的程序集版本相同
经过 上述三种中任意一种加载dll文件之后 可以通过 GetTypes 来获取程序集的type描述类的集合,里边包括,字段,属性,方法,构造函数等
例如:
Assembly assembly1 = Assembly.Load("MLab"); foreach (var item in assembly1.GetTypes()) { //这里还包括一些MLab的其他属性
var name= item.Name; var fullname= item.FullName;
//调用构造函数 无参构造方法 Activator.CreateInstance(item); Activator.CreateInstance(item, new object[] { }); //调用带参数的构造函数 var gz= Activator.CreateInstance(item, new object[] { "测试" }); //获取类里的方法 var typmethod= item.GetMethod("runstr"); ///想一下为什么在调用方法的时候要传递构造函数进去,【因为在程序执行的时候就是要先执行构造函数,也就是说程序的执行顺序本就该如此】 typmethod.Invoke(gz, new object[] { "方法测试" }); //带返回值 var typmethod1 = item.GetMethod("runstr1"); var retun1= typmethod1.Invoke(gz, new object[] { "带返回值的方法" }); Console.WriteLine(retun1); //获取所有方法 var typmethods= item.GetMethods(); //将获得的方法组进行骚操作。。。 foreach (var itemmethods in typmethods) {
// var name= itemmethods.Name; } } |
从上述一些简单的代码不难看出这个Type类是使用反射的关键类 ,在一个变量上调用GetType()方法,而不是把类型的名称作为其参数。但要注意,返回的Type对象仍只与该数据类型相关:它不包含与该类型的实例相关的任何信息。如果引用了一个对象,但不能确保该对象实际上是哪个类的实例,GetType方法就很有用。
double d = 10; Type t = d.GetType(); 获得t 是 Double 类型,但不是d赋值的int类型10(解释上边的描述) |
其中要注意的是,反射可以破坏单例,获取私有方法,
//获取私有方法 var typemethod = item.GetMethod("runstr2", BindingFlags.NonPublic | BindingFlags.Instance); |
关于反射获取特性
Attribute[] definedAttributes = Attribute.GetCustomAttributes(assembly1); // assembly1 is an Assembly object 这是获取相关的特性,在自定义特性时为什么必须费劲周折为他们编写类,以及 为什么没有更简单的语法。自定义特性与类一样,加载程序集之后,就可以读出这些属性,调用他们的方法 |