当前位置: 移动技术网 > IT编程>开发语言>.net > 浅谈.Net反射

浅谈.Net反射

2019年05月10日  | 移动技术网IT编程  | 我要评论

福福dy8,永无止境第一季,功夫派红人堂

一.何为反射?

reflection; 程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,就可以调用类型的方法或访问其字段和属性。

下图很好的解释了程序集和模块,类型等之间的关系: \

 

 

二.那些反射用到的类


1)反射核心类:system.type类

system. type类包装了类型,因此是整个反射子的核心,这个类中包含了很多属性和方法,使用这些属性和方法可以在运行时得到类型的信息. type类派生于system.reflection.memberinfo抽象类.(关于memberinfo,msdn上有解释,大家可以了解一下) 除了memberinfo类定义的方法和属性之外,type类自己也添加了许多方法和属性:如下表是常用的一些方法:
\

2)system.reflection.assembly类

通过assembly可以动态加载程序集,并查询程序集内部信息.assembly中有三种方法加载程序集:load,loadform,loadfile. *如果引用了命名空间,则就直接用load方法,参数里写上命名空间+类名就可加载。 *若仅仅知道一个dll文件,则就要用loadfrom方法,参数里直接填写完整的路径。loadfrom只能用于加载不同标识的程序集,即唯一的程序集,不能加载标识相同但路径不同的程序集。 * loadfile,加载指定路径上的程序集文件;与上述两方法不同的是:它不会加载此程序集中引用的其他的程 序集,且不会加载相同标识的程序集。 举例:
      //assembly通过此类可以加载操纵一个程序集,并获取程序集内部信息
      assembly assembly = assembly.load("myassembly"); //引用命名空间
      assembly assembly2 = assembly.loadfrom("d:\testdll.dll"); 
      assembly dll = assembly.loadfile(environment.currentdirectory + "\\testdll.dll");                                           //通过dll文件去反射其中所有的类型,但不会加载引用的程序集

 

三.如何使用反射?

1)要引用的程序集和需要程序集的程序在同一目录时,不需要加载程序集,直接可以获取其中的类型.举例:

 

      type math = type.gettype("testdll.math", true);    //获取类型
     
      methodinfo method = math.getmethod("add");  //获取testdll.math中的方法add
      int count = (int)method.invoke(null, new object[] { 10, 20 }); //给add方法传参数并去调用方法add
               
      console.writeline("invoke method:" + count.tostring()); 
      console.readline();

 

2)要引用的程序集合需要程序集不在同一目录中时,先要加载程序集,才能获取其中的类和类的方法等。举例:

      assembly dll = assembly.loadfile(environment.currentdirectory + "\\testdll.dll");   //通过dll文件去反射其中所有的类型,但不会加载引用的程序集
          //environment.currentdirectory 属性:获取或设置当前工作目录的完全限定路径              
      type math = dll.gettype("testdll.math", true);    //获取类型
     
      methodinfo method = math.getmethod("add");  //获取testdll.math中的方法add
      int count = (int)method.invoke(null, new object[] { 10, 20 }); //给add方法传参数并去调用方法add
               
      console.writeline("invoke method:" + count.tostring()); 
      console.readline();

 

 

 

3)反射+配置文件

看过大话设计模式的,都知道在抽象工厂模式中.小菜在大鸟的指点下,用简单工厂,再用反射,再用配置文件,一步步将抽象工厂改装, 使得抽象工厂的缺点和个各类之间的耦合性都大大降低.

 

不用反射+配置文件时,抽象工厂的问题是:
*如果需要增加多个,就要增加多个类,更麻烦。


在使用反射+配置文件后,抽象工厂的改变是:
*如果需要更换数据库,不需改变代码,只需要修改配置文件中db的值。

小结:反射技术的使用去除了switch或if,解除分支判断的耦合。在这里,反射可以说是简化了工厂的实现。

4)项目实践

在前段时间的项目开发中,就用到了反射。这里的用法和上述介绍的情况是一样的。用assembly类的load方法去加载程序集,用gettype去获取类型,getmethod去获取方法,invoke去调用方法,最后用savechanges去提交数据。举例:

        //ef:就是让ef上下文保存了一下。不适合于集群(后期使用key,value保存在分布式缓存中,key为guid)
        public int savechanges()
        {
            //return dbcontextfactory.getcurrentdbcontext().savechanges();


            string strassembly = configurationmanager.appsettings["dalassembly"];
            string strdbcontextfactoryclassfullename = configurationmanager.appsettings["dbcontextfactoryclassfullename"];


            assembly assembly = assembly.load(strassembly);
            type type = assembly.gettype(strdbcontextfactoryclassfullename);
            methodinfo methodinfo = type.getmethod("getcurrentdbcontext");
            return ((dbcontext)methodinfo.invoke(null, null)).savechanges();
        }

四.为什么要用反射?

反射与引用

相比较下,引用执行效率高,但是当你引用的dll文件很多的时候,一遍遍的引用dll...,那就不是什么好事了。 反射呢,虽执行效率低,但在上述情况出现时,它只需动态反射一次dll文件,不用去管dll文件时新增还是减少的情况了,有点一劳永逸的味道。

 

在真正用的过程中,反射回合委托,泛型,特性等等结合使用,这都是需要进一步研究学习的地方

 

 


 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网