IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection)。
作用:将各层的对象以松耦合的方式组织在一起,解耦,各层对象的调用完全面向接口。当系统重构的时候,代码的改写量将大大减少。
理解依赖注入:当一个类的实例需要另一个类的实例协助时,在传统的程序设计过程中,通常有调用者来创建被调用者的实例。然而采用依赖注入的方式,创建被调用者的工作不再由调用者来完成,因此叫控制反转,创建被调用者的实例的工作由IOC容器来完成,然后注入调用者,因此也称为依赖注入。
举个有意思的例子(来源于互联网)假如我们要设计一个Girl和一个Boy类,其中Girl有Kiss方法,即Girl想要Kiss一个Boy,首先问题是Girl如何认识Boy?在我们中国常见的MM认识GG的方式有以下几种:A 青梅竹马    B 亲友介绍   C 父母包办哪一种是最好的?
1.青梅竹马:很久很久以前,有个有钱的地主家的一闺女叫Lily,她老爸把她许配给县太爷的儿子Jimmy,属于指腹为婚,Lily非常喜欢kiss,但是只能kiss Jimmypublic class Lily{  public Jimmy jimmy;   public Girl()  {  jimmy=new Jimmy();  }  public void Kiss()  {  jimmy.Kiss();  }  }  public class Jimmy  {  public void Kiss()  {  Console.WriteLine("kissing");  }  }
这样导致Lily对Jimmy的依赖性非常强,紧耦合。2.亲友介绍:经常Kiss同一个人令Lily有些厌恶了,她想尝试新人,于是与Jimmy分手了,通过亲朋好友(中间人)来介绍public class Lily{  public Boy boy;   public Girl()  {  boy=BoyFactory.createBoy();  }  public void Kiss()  {  boy.Kiss();  }  }  亲友介绍,固然是好。如果不满意,尽管另外换一个好了。但是,亲友BoyFactory经常是以Singleton的形式出现,不然就是,存在于Globals,无处不在,无处不能。实在是太繁琐了一点,不够灵活。我为什么一定要这个亲友掺和进来呢?为什么一定要付给她介绍费呢?万一最好的朋友爱上了我的男朋友呢?3.父母包办:一切交给父母,自己不用非吹灰之力,Lily在家只Kisspublic class Lily{  public Boy boy;   public Girl(Boy boy)  {  this.boy=boy;  }  public void Kiss()  {  this.boy.Kiss();  }  }  Well,这是对Girl最好的方法,只要想办法贿赂了Girl的父母,并把Boy交给他。那么我们就可以轻松的和Girl来Kiss了。看来几千年传统的父母之命还真是有用哦。至少Boy和Girl不用自己瞎忙乎了。这就是IOC,将对象的创建和获取提取到外部。由外部容器提供需要的组件。在设计模式中我们应该还知道依赖倒转原则,应是面向接口编程而不是面向功能实现,好处是:多实现可以任意切换,我们的Boy应该是实现Kissable接口。这样一旦Girl不想kiss可恶的Boy的话,还可以kiss可爱的kitten和慈祥的grandmother好在.net中微软有一个轻量级的IoC框架Unity,支持构造器注入,属性注入,方法注入如下图所示具体使用方法如下图所示using System;  using Microsoft.Practices.Unity;  namespace ConsoleApplication9
{  class Program  {  static void Main(string[] args)  {  //创建容器  IUnityContainer container=new UnityContainer();  //注册映射  container.RegisterType<IKiss, Boy>();  //得到Boy的实例  var boy = container.Resolve<IKiss>();  Lily lily = new Lily(boy);  lily.kiss();  }  }  public interface IKiss  {  void kiss();  }  public class Lily:IKiss  {  public IKiss boy;   public Lily(IKiss boy)  {  this.boy=boy;  }  public void kiss()  {  boy.kiss();  Console.WriteLine("lily kissing");  }  }  public class Boy : IKiss  {  public void kiss()  {  Console.WriteLine("boy kissing");  }  }
}
如果采用配置文件注册的话<?xml version="1.0" encoding="utf-8" ?>
<configuration>  <configSections>  <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>  </configSections>  <unity>  <containers>  <container name="defaultContainer">  <register type="命名空间.接口类型1,命名空间" mapTo="命名空间.实现类型1,命名空间" />  <register type="命名空间.接口类型2,命名空间" mapTo="命名空间.实现类型2,命名空间" />  </container>  </containers>  </unity>
</configuration>  配置的后台代码:UnityConfigurationSection configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName)  as UnityConfigurationSection;
configuration.Configure(container, "defaultContainer");
可以通过方法ResolveAll来得到所有注册对象的实例:
var Instances = container.Resolve<IKiss>();Martin Fowler在那篇著名的文章《Inversion of Control Containers and the Dependency Injection pattern》中将具体依赖注入划分为三种形式,即构造器注入、属性(设置)注入和接口注入,习惯将其划分为一种(类型)匹配和三种注入:类型匹配(Type Matching):虽然我们通过接口(或者抽象类)来进行服务调用,但是服务本身还是实现在某个具体的服务类型中,这就需要某个类型注册机制来解决服务接口和服务类型之间的匹配关系;
构造器注入(Constructor Injection):IoC容器会智能地选择选择和调用适合的构造函数以创建依赖的对象。如果被选择的构造函数具有相应的参数,IoC容器在调用构造函数之前解析注册的依赖关系并自行获得相应参数对象;
属性注入(Property Injection):如果需要使用到被依赖对象的某个属性,在被依赖对象被创建之后,IoC容器会自动初始化该属性;
方法注入(Method Injection):如果被依赖对象需要调用某个方法进行相应的初始化,在该对象创建之后,IoC容器会自动调用该方法。我们创建一个控制台程序,定义如下几个接口(IA、IB、IC和ID)和它们各自的实现类(A、B、C、D)。在类型A中定义了3个属性B、C和D,其类型分别为接口IB、IC和ID。其中属性B在构在函数中被初始化,以为着它会以构造器注入的方式被初始化;属性C上应用了DependencyAttribute特性,意味着这是一个需要以属性注入方式被初始化的依赖属性;属性D则通过方法Initialize初始化,该方法上应用了特性InjectionMethodAttribute,意味着这是一个注入方法在A对象被IoC容器创建的时候会被自动调用。public interface IA { }  public interface IB { }  public interface IC { }  public interface ID { }  public class A : IA  {  public IB B { get; set; }  [Dependency]  public IC C { get; set; }  public ID D { get; set; }  public A(IB b)  {  this.B = b;  }  [InjectionMethod]  public void Initalize(ID d)  {  this.D = d;  }  }  public class B : IB { }  public class C : IC { }  public class D : ID { }  然后我们为该应用添加一个配置文件,并定义如下一段关于Unity的配置。这段配置定义了一个名称为defaultContainer的Unity容器,并在其中完成了上面定义的接口和对应实现类之间映射的类型匹配。<?xml version="1.0" encoding="utf-8" ?>
<configuration>  <configSections>  <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>  </configSections>  <unity>  <containers>  <container name="defaultContainer">  <register type="UnityDemo.IA,UnityDemo" mapTo="UnityDemo.A, UnityDemo"/>  <register type="UnityDemo.IB,UnityDemo" mapTo="UnityDemo.B, UnityDemo"/>  <register type="UnityDemo.IC,UnityDemo" mapTo="UnityDemo.C, UnityDemo"/>  <register type="UnityDemo.ID,UnityDemo" mapTo="UnityDemo.D, UnityDemo"/>  </container>  </containers>  </unity>
</configuration>  最后在Main方法中创建一个代表IoC容器的UnityContainer对象,并加载配置信息对其进行初始化。然后调用它的泛型的Resolve方法创建一个实现了泛型接口IA的对象。最后将返回对象转变成类型A,并检验其B、C和D属性是否是空class Program  {  static void Main(string[] args)  {  UnityContainer container = new UnityContainer();  UnityConfigurationSection configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;  configuration.Configure(container, "defaultContainer");  A a = container.Resolve<IA>() as A;  if (null!=a)  {  Console.WriteLine("a.B==null?{0}",a.B==null?"Yes":"No");  Console.WriteLine("a.C==null?{0}", a.C == null ? "Yes" : "No");  Console.WriteLine("a.D==null?{0}", a.D == null ? "Yes" : "No");  }  }  }  从如下给出的执行结果我们可以得到这样的结论:通过Resolve<IA>方法返回的是一个类型为A的对象,该对象的三个属性被进行了有效的初始化。这个简单的程序分别体现了接口注入(通过相应的接口根据配置解析出相应的实现类型)、构造器注入(属性B)、属性注入(属性C)和方法注入(属性D)a.B == null ? Noa.C == null ? Noa.D == null ? No

http://www.cnblogs.com/zhangchenliang/archive/2013/01/08/2850970.html

IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection)。
作用:将各层的对象以松耦合的方式组织在一起,解耦,各层对象的调用完全面向接口。当系统重构的时候,代码的改写量将大大减少。
理解依赖注入:
    当一个类的实例需要另一个类的实例协助时,在传统的程序设计过程中,通常有调用者来创建被调用者的实例。然而采用依赖注入的方式,创建被调用者的工作不再由调用者来完成,因此叫控制反转,创建被调用者的实例的工作由IOC容器来完成,然后注入调用者,因此也称为依赖注入。
举个有意思的例子(来源于互联网)

假如我们要设计一个Girl和一个Boy类,其中Girl有Kiss方法,即Girl想要Kiss一个Boy,首先问题是Girl如何认识Boy?
在我们中国常见的MM认识GG的方式有以下几种:
A 青梅竹马    B 亲友介绍   C 父母包办
哪一种是最好的?

1.青梅竹马:很久很久以前,有个有钱的地主家的一闺女叫Lily,她老爸把她许配给县太爷的儿子Jimmy,属于指腹为婚,Lily非常喜欢kiss,但是只能kiss Jimmy

  1. public class Lily{
  2. public Jimmy jimmy;
  3. public Girl()
  4. {
  5. jimmy=new Jimmy();
  6. }
  7. public void Kiss()
  8. {
  9. jimmy.Kiss();
  10. }
  11. }
  12. public class Jimmy
  13. {
  14. public void Kiss()
  15. {
  16. Console.WriteLine("kissing");
  17. }
  18. }

这样导致Lily对Jimmy的依赖性非常强,紧耦合。

2.亲友介绍:经常Kiss同一个人令Lily有些厌恶了,她想尝试新人,于是与Jimmy分手了,通过亲朋好友(中间人)来介绍

  1. public class Lily{
  2. public Boy boy;
  3. public Girl()
  4. {
  5. boy=BoyFactory.createBoy();
  6. }
  7. public void Kiss()
  8. {
  9. boy.Kiss();
  10. }
  11. }

亲友介绍,固然是好。如果不满意,尽管另外换一个好了。但是,亲友BoyFactory经常是以Singleton的形式出现,不然就是,存在于Globals,无处不在,无处不能。实在是太繁琐了一点,不够灵活。我为什么一定要这个亲友掺和进来呢?为什么一定要付给她介绍费呢?万一最好的朋友爱上了我的男朋友呢?

3.父母包办:一切交给父母,自己不用非吹灰之力,Lily在家只Kiss

  1. public class Lily{
  2. public Boy boy;
  3. public Girl(Boy boy)
  4. {
  5. this.boy=boy;
  6. }
  7. public void Kiss()
  8. {
  9. this.boy.Kiss();
  10. }
  11. }

Well,这是对Girl最好的方法,只要想办法贿赂了Girl的父母,并把Boy交给他。那么我们就可以轻松的和Girl来Kiss了。看来几千年传统的父母之命还真是有用哦。至少Boy和Girl不用自己瞎忙乎了。这就是IOC,将对象的创建和获取提取到外部。由外部容器提供需要的组件。

在设计模式中我们应该还知道依赖倒转原则,应是面向接口编程而不是面向功能实现,好处是:多实现可以任意切换,我们的Boy应该是实现Kissable接口。这样一旦Girl不想kiss可恶的Boy的话,还可以kiss可爱的kitten和慈祥的grandmother

好在.net中微软有一个轻量级的IoC框架Unity,支持构造器注入,属性注入,方法注入如下图所示

具体使用方法如下图所示

  1. using System;
  2. using Microsoft.Practices.Unity;
  3. namespace ConsoleApplication9
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. //创建容器
  10. IUnityContainer container=new UnityContainer();
  11. //注册映射
  12. container.RegisterType<IKiss, Boy>();
  13. //得到Boy的实例
  14. var boy = container.Resolve<IKiss>();
  15. Lily lily = new Lily(boy);
  16. lily.kiss();
  17. }
  18. }
  19. public interface IKiss
  20. {
  21. void kiss();
  22. }
  23. public class Lily:IKiss
  24. {
  25. public IKiss boy;
  26. public Lily(IKiss boy)
  27. {
  28. this.boy=boy;
  29. }
  30. public void kiss()
  31. {
  32. boy.kiss();
  33. Console.WriteLine("lily kissing");
  34. }
  35. }
  36. public class Boy : IKiss
  37. {
  38. public void kiss()
  39. {
  40. Console.WriteLine("boy kissing");
  41. }
  42. }
  43. }

如果采用配置文件注册的话

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3. <configSections>
  4. <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  5. </configSections>
  6. <unity>
  7. <containers>
  8. <container name="defaultContainer">
  9. <register type="命名空间.接口类型1,命名空间" mapTo="命名空间.实现类型1,命名空间" />
  10. <register type="命名空间.接口类型2,命名空间" mapTo="命名空间.实现类型2,命名空间" />
  11. </container>
  12. </containers>
  13. </unity>
  14. </configuration>

配置的后台代码:

  1. UnityConfigurationSection configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName)
  2. as UnityConfigurationSection;
  3. configuration.Configure(container, "defaultContainer");

可以通过方法ResolveAll来得到所有注册对象的实例:
var Instances = container.Resolve<IKiss>();

Martin Fowler在那篇著名的文章《Inversion of Control Containers and the Dependency Injection pattern》中将具体依赖注入划分为三种形式,即构造器注入、属性(设置)注入和接口注入,习惯将其划分为一种(类型)匹配和三种注入:

  • 类型匹配(Type Matching):虽然我们通过接口(或者抽象类)来进行服务调用,但是服务本身还是实现在某个具体的服务类型中,这就需要某个类型注册机制来解决服务接口和服务类型之间的匹配关系;
  • 构造器注入(Constructor Injection):IoC容器会智能地选择选择和调用适合的构造函数以创建依赖的对象。如果被选择的构造函数具有相应的参数,IoC容器在调用构造函数之前解析注册的依赖关系并自行获得相应参数对象;
  • 属性注入(Property Injection):如果需要使用到被依赖对象的某个属性,在被依赖对象被创建之后,IoC容器会自动初始化该属性;
  • 方法注入(Method Injection):如果被依赖对象需要调用某个方法进行相应的初始化,在该对象创建之后,IoC容器会自动调用该方法。

我们创建一个控制台程序,定义如下几个接口(IA、IB、IC和ID)和它们各自的实现类(A、B、C、D)。在类型A中定义了3个属性B、C和D,其类型分别为接口IB、IC和ID。其中属性B在构在函数中被初始化,以为着它会以构造器注入的方式被初始化;属性C上应用了DependencyAttribute特性,意味着这是一个需要以属性注入方式被初始化的依赖属性;属性D则通过方法Initialize初始化,该方法上应用了特性InjectionMethodAttribute,意味着这是一个注入方法在A对象被IoC容器创建的时候会被自动调用。

  1. public interface IA { }
  2. public interface IB { }
  3. public interface IC { }
  4. public interface ID { }
  5. public class A : IA
  6. {
  7. public IB B { get; set; }
  8. [Dependency]
  9. public IC C { get; set; }
  10. public ID D { get; set; }
  11. public A(IB b)
  12. {
  13. this.B = b;
  14. }
  15. [InjectionMethod]
  16. public void Initalize(ID d)
  17. {
  18. this.D = d;
  19. }
  20. }
  21. public class B : IB { }
  22. public class C : IC { }
  23. public class D : ID { }

然后我们为该应用添加一个配置文件,并定义如下一段关于Unity的配置。这段配置定义了一个名称为defaultContainer的Unity容器,并在其中完成了上面定义的接口和对应实现类之间映射的类型匹配。

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3. <configSections>
  4. <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  5. </configSections>
  6. <unity>
  7. <containers>
  8. <container name="defaultContainer">
  9. <register type="UnityDemo.IA,UnityDemo" mapTo="UnityDemo.A, UnityDemo"/>
  10. <register type="UnityDemo.IB,UnityDemo" mapTo="UnityDemo.B, UnityDemo"/>
  11. <register type="UnityDemo.IC,UnityDemo" mapTo="UnityDemo.C, UnityDemo"/>
  12. <register type="UnityDemo.ID,UnityDemo" mapTo="UnityDemo.D, UnityDemo"/>
  13. </container>
  14. </containers>
  15. </unity>
  16. </configuration>

最后在Main方法中创建一个代表IoC容器的UnityContainer对象,并加载配置信息对其进行初始化。然后调用它的泛型的Resolve方法创建一个实现了泛型接口IA的对象。最后将返回对象转变成类型A,并检验其B、C和D属性是否是空

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. UnityContainer container = new UnityContainer();
  6. UnityConfigurationSection configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;
  7. configuration.Configure(container, "defaultContainer");
  8. A a = container.Resolve<IA>() as A;
  9. if (null!=a)
  10. {
  11. Console.WriteLine("a.B==null?{0}",a.B==null?"Yes":"No");
  12. Console.WriteLine("a.C==null?{0}", a.C == null ? "Yes" : "No");
  13. Console.WriteLine("a.D==null?{0}", a.D == null ? "Yes" : "No");
  14. }
  15. }
  16. }

从如下给出的执行结果我们可以得到这样的结论:通过Resolve<IA>方法返回的是一个类型为A的对象,该对象的三个属性被进行了有效的初始化。这个简单的程序分别体现了接口注入(通过相应的接口根据配置解析出相应的实现类型)、构造器注入(属性B)、属性注入(属性C)和方法注入(属性D)

  a.B == null ? No
 a.C == null ? No
 a.D == null ? No

转载于:https://www.cnblogs.com/wangchuang/p/5650911.html

理解依赖注入(IOC)和学习Unity相关推荐

  1. ASP.NET CORE 第四篇 依赖注入IoC学习 + AOP界面编程初探

    原文作者:老张的哲学 更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjo ...

  2. 从壹开始前后端分离【 .NET Core2.2 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探...

    更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjoy8/BlogArti ...

  3. 理解依赖注入(IOC)

    IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection). 作用:将各层的对象以松耦合的方式组织在一起,解耦, ...

  4. [转]依赖注入(IOC)的详细讲解,附带实例和测试结果(大师兄亲测)

    原文链接:http://blog.csdn.net/qq_27093465/article/details/52547290 版权声明:觉得此文有用的,不嫌麻烦的,就留个言呐,或者点个赞呐(额,就是文 ...

  5. 深度理解依赖注入(Dependence Injection)

    前面的话:提到依赖注入,大家都会想到老马那篇经典的文章.其实,本文就是相当于对那篇文章的解读.所以,如果您对原文已经有了非常深刻的理解,完全不需要再看此文:但是,如果您和笔者一样,以前曾经看过,似乎看 ...

  6. Go工程化 - 手摸手带你理解依赖注入

    转载地址:https://mp.weixin.qq.com/s/c7JtKKCGSD5x9c4TxqzghQ 我们在微服务框架 kratos v2[1] 的默认项目模板中 kratos-layout[ ...

  7. ioc控制反转_深入理解依赖注入(DI)和控制反转(IOC)

    转载本文务必须注明出处.微信号(Yemeir_com).以及添加原文链接. 为什么要使用依赖注入 使用依赖注入(DI)可以使控制者与抽象实现者松耦合,便于单元测试.通过控制反转(IOC)的设计原理来减 ...

  8. 如何理解依赖注入(DI)

    什么是依赖注入(Dependency Injection) 依赖倒置原则:高层模块不应该依赖于低层模块,两个都应该依赖于抽象(接口). 依赖倒置是一种软件设计思想,在传统软件中,上层代码依赖于下层代码 ...

  9. 依赖注入框架Autofac学习笔记

    Autofac是一个轻量级的依赖注入框架,可以在这里面下载:http://code.google.com/p/autofac/downloads/list 要想了解什么是依赖注入,可以参考下这篇博客: ...

最新文章

  1. JavaScript 消息框
  2. 改写Unity DropDown 支持多次点击同一选项均回调
  3. linux 回退乱码,如何在linux sqlplus 下实现方向健和回退键操作而避免乱码
  4. rhel 6下配置网络yum源(虚拟机环境下)
  5. 隐藏在计算机网卡怎样删除,如何卸载电脑中隐藏的虚拟网卡设备
  6. android compile使用方法,自己创建一个android studio在线依赖compile
  7. 4固定在底部_礼堂椅厂家教你如何固定座椅
  8. html弹出保存文件对话框_有没有遇到过CAD文件损坏或打不开的情况?养成这个习惯很重要...
  9. c/c++多参数的问题
  10. 上一页下一页_多页PDF文件也能很快合为一页PDF文件?这个小技巧可以办到
  11. microsoft excel正在等待其他某个应用程序_如何删除 Mac 储存空间的其他选项?
  12. VSTS 2010体验 - TFS 2010变化巨大
  13. iPhone质量成迷?被吴彦祖一箭射穿,却还能开机
  14. 机器学习基础算法33-HMM实践
  15. 浅谈极限编程(更新中)
  16. 2020年书法落款_书法落款的基本常识最新版
  17. phalapi做登录检测_欢迎使用PhalApi!
  18. Lenovo 使用BoMC工具制作微码升级U盘刷新System x
  19. 软件工程师学习硬件原理图--第一讲看懂GPIO和门电路(弱智学前班儿童系列)
  20. html5:制作一份邀请函

热门文章

  1. Linux 命令之 stat -- 显示文件的状态信息
  2. WebService入门介绍
  3. 服务中心Eureka
  4. mysql主从修改系统参数步骤_mysql主从配置的参数配置与步骤_MySQL
  5. cookies丢失 同域名_后端设置Cookie前端跨域获取丢失问题(基于springboot实现)
  6. centos7设置键盘类型_CentOS 7 系统区域(语言)和键盘设置
  7. 在建工地扬尘在线监控系统推荐_vocs在线监控系统安装的法规依据
  8. binlog日志_MySQL三大日志binlog、redo log和undo log
  9. 计算机应用能力文字录入,2017全国专业技术人员计算机应用能力考试题库-Excel,Word,XP.pdf...
  10. RS485集线器知识详解