反射机制、依赖注入、控制反转

反射机制

正向: 代码->dll, 先编码, 定义好类,通过实例化对象来调用之.

反向: dll->类[方法,属性]. 从已经有的dll文件反编译得到其中的一些可用的方法.

审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等。

System.reflection命名空间包含的几个类,允许你反射(解析)这些元数据表的代码。

反射是.Net中获取 运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,例如:

通常程序员面试题,有这样关于反射的解释:反射可以动态地创建类型的实例,还可以将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。

主要用途是:通过传递一个字符串值, 在运行时构造一个类的对象, 判断一个类所具有的成员变量和方法;调用一个对象的方法;生成动态代理。反射最大的应用就是框架

正常处理过程:系统在运行的时候将把dll(动态链接库)加载到当 前进程的一个默认的应用程序域application.currentdomain.load方法可以取得当前域的所有dll,也可以unload方法将 dll从该域卸载掉,通过执行dll的方法来响应用户的操作,执行完后,就释放了这个dll,这是运行时的行为这里dll相当于一个工具集, 工具箱. 用户只得到这个工具箱, 按下相应接口按钮可以完成对应的任务。

反射: 反过来看,你可以从当前进程的应用程序域取得DLL开始(application.currentdomain.load取出该进程的所有的DLL列表),取得DLL里的类列表或者其他模块,然后调用类的方法,相当于打开了工具箱, 取其中的一些工具来.

也就是说,正常的顺序是,知道一个确定的类以及里面的属性、方法。然后实例化一个对象,调用它的方法来执行。

反射就是只有一个DLL文件,知道类名却不知道他有什么属性和方法,可以通过反射机制来动态加载程序集得到类中的属性、方法信息,并实例化一个对象等

例如本来有一个类

namespace A{

public class A{

public int methodA(string s);

public int methodB(int i);

public int c;

}

}

如果只给你这个dll工程编译出的dll文件

可以用system.reflection中的一些个方法来得到其中的具体的属性/方法等..

string asmFile = "path of dll".

System.Reflection.Assembly asm = System.Reflection.Assembly.LoadFrom(asmFile) ;

MemberInfo[] mi = asm.GetType(asmName + "." + asmName).GetMethods();

Type t =  asm.GetType(命名空间.类名); 用t来访问具体的方法..

类名: method = System.Activator.CreateInstance(t);

类名可以通过getname来得到..

总结反射:

别被吓唬了,原理其实很简单,.net所编写的程序集包含两个重要部分:IL(中间语言代码) 和metadata(元数据)。我们编写的代码中不是有很多很多的类吗,类有很多很多的成员,在编译代码的时候,元数据表就根据代码把类的所有信息都记录在了它里面(其实它就是一个数据结构,组织类的信息)。

而反射的过程刚好相反,就是通过元数据里记录的关于类的详细信息找到该类的成员,并能使它“复活”(因为元数据里所记录的信息足够详细,以致于可以根据metadata里面记录的信息找到关于该类的IL code并加以利用)。

最后对比下:

元数据形成:根据代码具体内容形成类的记录信息;

反射:根据元数据的记录找到所需的代码;

至于实例,用Type类实现很方便:

Type t = typeof(System.string);

MemberInfo[] mis = t.GetMembers();

foreach (MemberInfo mi in mis)

{

Console.WriteLine(mi.MemberType + mi.Name);

}

就会得到关于String类的所有信息;

控制反转、依赖注入

控制反转(Inversion of
Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。
控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。

依赖注入:

依赖注入和控制反转是同一个概念。具体含义是:
当某个角色(一个实例,调用者)需要另一个角色(另一个实例,被调用者)的协助时,在传统的程序设计过程中,通常有调用者来创建被调用者的实例。但在
Spring里,创建被调用者的工作不再由调用者来完成,因此成为控制反转;创建被调用者实例的工作通常有Spring容器来完成,然后注入到调用者,因
此也称为依赖注入。

不管是依赖注入,还是控制反转,多说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现相互透明。看如下这个问题在各种社会形态里如何解决:一个人(实例,调用者)需要一把斧子(实例,被调用者)。

(1).原始社会里,几乎没有社会分工。需要一把斧子的人(调用者)只能自己去磨一把斧子(被调用者)。对应的情形为:Java或C#程序里的调用者自己创建被调用者。

(2).进入工业社会,工厂出现。斧子不再由普通人完成,而在工厂里被生产出来,此时需要斧子的人(调用者)找到工厂,购买斧子,无需关系斧子的制造过程。对应程序的简单工厂设计模式。

(3).进入“按需分配”社会,需要斧子的人不需要找到工厂,坐在家里发出一个简单指令:需要斧子。斧子就自然出现在它面前。对应Spring的依赖注入。

第一种情况下,Java或C#实例的调用者创建被调用的实例,必然要求被调用的类出现在调用者的代码里。无法实现二者之间的松耦合。

第二种情况下,调用者无需关心被调用者具体实现过程,只需要找到符合某种标准(接口)的实例,即可使用。此时调用的代码面向接口编程,可以让调用者和被调用者解耦,这也是工厂模式大量使用的原因。但调用者需要自己定位工厂,调用者与特定工厂耦合在一起。

第三种情况下,调用者无需自己定位工厂,程序运行到需要被调用者时,系统自动提供被调用者实例。事实上,调用者和被调用者都处于Spring的管理下,二者之间的依赖关系有Spring提供。

所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无需在代码中创建被调用者,而是依赖于外部的注入。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。

依赖注入(控制反转)是Spring框架的核心。

应用控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体(可以理解为后面所说的容器)将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。所以,控制反转是,关于一个对象如何获取他所依赖的对象的引用,这个责任的反转。原来依赖关系是调用者调用被调用者,现在反过来是被调用者注册到调用者。

换句话说,就是在运行的时候才产生调用者实例和被调用者实例之间的依赖关系(吧这
种依赖关系在一个合适的时候“注入”运行时),恐怕就是DI(Dependency
Injection)这个术语的由来。再换句话说,我们提到过解除强依赖,这并不是说调用者和被调用者之间的一览关系不存在了,事实上调用者无论如何也需
要某类被调用者提供的服务,我们只是把何种依赖的建立时间推后了,从编译器推迟到了运行时。依赖关系在OO程序中是广泛存在的,只要A类型中用到了B类型
实例,A就依赖于B。前面笔者淡到的内容是把概念抽象到了服务使用者和服务提供者的角度,这也符合现在SOA的设计思路。从另一种抽象方式上来看,可以把
调用者看成我们要构建的主系统,而被调用者实例是系统中的plugin,主系统并不强依赖于任何一个插件,但一旦插件被加载,主系统就应该可以准确调用适
当插件的功能。

其实不管是面向服务的编程模式,还是基于插件的框架式编程,为了实现松耦合(服务调用者和提供者之间的or框架和插件之间的),都需要在必要的位置实现面向接口编程,在此基础之上,还应该有一种方便的机制实现具体类型之间的运行时绑定,这就是DI所要解决的问题。

说白了,就是要提供一个容器,由容器来完成(1)具体ServiceProvider的创建(2)ServiceUser和ServiceProvider的运行时绑定。特别说明的是,要理解依赖注入的机制,关键是理解容器的实现方式。

IoC可以认为是一种全新的设计模式,但是理论和时间成熟相对较晚,并没有包含在GoF中。

Interface Driven
Design接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,也就是如下语句迟早要执行:AInterface
a = new AInterfaceImp(); 这样一来,耦合关系就产生了,如:

Class
A与AInterfaceImp就是依赖关系,如果想使用AInterface的另外一个实现就需要更改代码了。当然我们可以建立一个Factory来根据条件生成想要的AInterface的具体实现,即:

表面上是在一定程度上缓解了以上问题,但实质上这种代码耦合并没有改变。通过IoC模式可以彻底解决这种耦合,它把耦合从代码中移出去,放到统一的XML
文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中,这可能就是“依赖注入”说法的来源了。

IOC模式,系统中通过引入实现了IOC模式的IOC容器,即可由IOC容器来管理对象的生命周期、依赖关系等,从而使得应用程序的配置和依赖性规范与实际的应用程序代码分开。其中一个特点就是通过文本的配置文件进行应用程序组件间相互关系的配置,而不用重新修改并编译具体的代码。

当前比较知名的IOC容器有:Pico
Container、Avalon 、Spring、JBoss、HiveMind、EJB等。

在上面的几个IOC容器中,轻量级的有Pico
Container、Avalon、Spring、HiveMind等,超重量级的有EJB,而半轻半重的有容器有JBoss,Jdon等。

可以把IoC模式看做是工厂模式的升华,可以把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java
的“反射”编程,根据XML中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

IoC中最基本的Java技术就是“反射”编程。反射又是一个生涩的名词,通俗的说反射就是根据给出的类名(字符串)来生成对象。这种编程方式可以让对象在生成时才决定要生成哪一种对象。反射的应用是很广泛的,象Hibernate、Spring中都是用“反射”做为最基本的技术手段。

在过去,反射编程方式相对于正常的对象生成方式要慢10几倍,这也许也是当时为什么反射技术没有普遍应用开来的原因。但经SUN改良优化后,反射方式生成对象和通常对象生成方式,速度已经相差不大了(但依然有一倍以上的差距)。

时间: 2024-10-09 23:41:08

反射机制、依赖注入、控制反转的相关文章

Helloworld之Spring依赖注入/控制反转(DI/IoC)版

Helloworld之Spring依赖注入/控制反转(DI/IoC)版 作者:雨水, 日期:2014-10-29 摘要:本文主要用于培训初学者理解Spring中的依赖注入的基本概念. 先介绍依赖注入的基本概念,然后以构造器注入为例实现了Helloworld实例. Spring依赖注入/控制反转 在我们通常的编程中,如果类A要依赖类B,通常是由A来创建一个B的实例.而Spring将创建B的实例的工作交给Spring容器来完成,然后注入A,因此称为依赖注入(DI, Dependency Inject

PHP关于依赖注入(控制反转)的解释和例子说明

PHP关于依赖注入(控制反转)的解释和例子说明 发表于2年前(2014-03-20 10:12)   阅读(726) | 评论(1) 8人收藏此文章, 我要收藏 赞2 阿里云双11绽放在即 1111 元红包即刻开抢!»   摘要 自从听到依赖注入这个设计模式,感觉很高大上,无奈楼主的眼光一直局限在国内框架上,也很少去关注设计模式方面的文章,直到某天遇到了laravel后,发现它手册里重点强调了一个名为“依赖注入”和“容器”的概念,但是对于这两个概念,手册里并未做基本的解释,所以楼主只能另外查找相

C#依赖注入控制反转IOC实现详解

原文:C#依赖注入控制反转IOC实现详解 IOC的基本概念是:不创建对象,但是描述创建它们的方式.在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务.容器负责将这些联系在一起. 举个例子,组件A中有类ClassA,组件B中有接口IB和其对应的实现类B1和B2. 那么,现在ClassA需要利用IB接口来做一些事情,例如: public class ClassA { public void DoSomething() { IB b = ??? b.DoWork(); }} 现

Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

我们常常会遇到这样一种情景.就是在我们开发项目的时候常常会在一个类中调用其它的类中的方法,来完毕我们期望的任务.大部分的情况下往往会採用在当前需要的这个类里面new一个实例出来.然后调用他的方法,那么这种话会有个问题.就是有一天我想改变下这个类,改为其它的名称.那么这时候必需要做的是同一时候去调用方的类文件里改变这个改变的类的名称.这种情况是由于代码的耦合带来了后期维护成本的添加,那么spring的出现就能够非常好的起到解耦的作用,而他的核心机制就是依赖注入. 依赖注入与控制反转 依赖注入:对于

分层,工厂模式,依赖注入控制反转

1.分层:就如同一个人自己制造一个锤子,自己动手丰衣足食.你需要他就自己new一个该实例.无法实现二者之间的松耦合 2.工厂模式:一个人需要一个锤子,他找工厂,工厂帮他造了一个锤子.工厂给你制造的锤子,但是如何造的你不需要知道.你直接调用该接口就可以了,具体你不需要知道.调用者无须关心被调用者具体实现过程,只需要找到符合某种标准(接口)的实例,即可使用 3.依赖注入:一个人需要一个锤子,他打电话给卖锤子的叫他送货上门.你喜欢哪家的锤子,直接叫哪家送货上门就OK.用者无须自己定位工厂,程序运行到需

大话依赖倒置?控制反转?依赖注入?面向接口编程

那些年,空气中仿佛还能闻到汉唐盛世的余韵,因此你决不允许自己的脸上有油光,时刻保持活力.然而,你一定曾为这些“高深术语”感到过困扰——依赖倒置•控制反转•依赖注入•面向接口编程.也许时至今日,你仍对它们一知半解.不过就在今天,这一切都将彻底改变!我将带领你以一种全新的高清视角进入奇妙的编程世界,领略涵泳在这些“高深术语”中的活泼泼的地气,以及翩跹于青萍之末的云水禅心. ·内聚 内聚,通俗的来讲,就是自己的东西自己保管,自己的事情自己做. 经典理论告诉我们,程序的两大要素:一个是数据(data),

依赖倒置,控制反转,依赖注入

好的文章,总是担心消失,自己保存一遍,这里是原文 向依赖关系宣战 依赖倒置.控制反转和依赖注入辨析在<道法自然——面向对象实践指南>一书中,我们采用了一个对立统一的辩证关系来说明“模板方法”模式—— “正向依赖 vs. 依赖倒置”(参见:<道法自然>第15章[王咏武, 王咏刚 2004]).这种把“好莱坞”原则和 “依赖倒置”原则等量齐观的看法其实来自于轻量级容器PicoContainer主页上的一段话: “控制反转(Inversion of Control)的一个著名的同义原则是

那些年搞不懂的高深术语——依赖倒置?控制反转?依赖注入?面向接口编程

那些年,空气中仿佛还能闻到汉唐盛世的余韵,因此你决不允许自己的脸上有油光,时刻保持活力.然而,你一定曾为这些“高深术语”感到过困扰.也许时至今日,你仍对它们一知半解.不过就在今天,这一切都将彻底改变!我将带领你以一种全新的高清视角进入奇妙的编程世界,领略涵泳在这些“高深术语”中的活泼泼的地气,以及翩跹于青萍之末的云水禅心. ·内聚 内聚,通俗的来讲,就是自己的东西自己保管,自己的事情自己做. 经典理论告诉我们,程序的两大要素:一个是数据(data),一个是操作(opration).而 PASCA

通俗简述 依赖倒置?控制反转?依赖注入?面向接口编程 的思想

不管怎样我们都是为了提倡高内聚和低耦合的思想,这么多种思想是不是看那些概念头晕的不行呢? 这里我们主要列举吃饭的例子让大家更直观的理解这几个概念,现在有顾客(客户端)与餐厅(服务端)两个对象 依赖倒置: 餐厅建立订餐通道  (本来是顾客依赖餐厅炒菜的,开通饿了吗后餐厅就倒过来依赖ele的订单去炒菜了) 控制反转IOC(Inversion Of Control):  改成自助餐厅(以前餐厅炒的菜分量太少了,现在菜都摆出来了你可以自己选择量多的菜了) 依赖注入DI(Dependency Inject

spring-第一篇之spring核心机制依赖注入(DI)/控制翻转(IoC)

1.spring的核心机制:依赖注入(DI)/控制翻转(IoC) 什么是依赖:A对象需要调用B对象,所以A依赖于B. 什么是注入:A对象注入一个属性B对象. 什么是依赖注入(DI):A对象依赖于B对象,spring容器负责将B对象添加到A对象中,即将A对象的依赖对象B添加到A对象中. 什么是控制翻转(IoC):A对象依赖于B对象,它将通过new B对象的方式主动获取得B对象实例:但spring则将B对象直接送到A面前供其使用,A被动接受B对象. 依赖注入(DI)与控制翻转(IoC)的关系:只是从