为了更好地理解依赖注入的概念,首先了解一下软件设计模式是颇有必要的。软件设计模式主要用来规范问题及其解决方案的描述,以简化开发人员对常见问题及其对应解决方案的标识与交流。设计模式
几乎每一个人都看过或是本身写过下面代码的经历服务器
1 public class EmailService 2 { 3 public void SendMsg() 4 { 5 Console.WriteLine("Hello world !!!"); 6 } 7 } 8 9 /// <summary> 10 /// 耦合实现 11 /// </summary> 12 public class NotificationSys 13 { 14 private EmailService svc; 15 16 public NotificationSys() 17 { 18 svc = new EmailService(); 19 } 20 21 public void InterestingEventHappened() 22 { 23 svc.SendMsg(); 24 } 25 }
上述代码中,NotificationSys 类依赖EmailService类,当一个组件依赖其余组件称之耦合。在软件设计过程,高耦合一般认为是软件设计的责任。当一个类精确地知道另外一个类的设计和实现时,就会增长软件修改的负担,由于修改一个类颇有可能破坏依赖它的另外一个类。为下降组件之间的耦合程序,通常采起两个独立但相关的步骤:app
1.在两块代码之间引入抽象层,因此上述代码可修改成如下ide
1 public interface IEmailService 2 { 3 void SendMsg(); 4 } 5 public class EmailService : IEmailService 6 { 7 public void SendMsg() 8 { 9 Console.WriteLine("Hello world !!!"); 10 } 11 } 12 /// <summary> 13 /// 抽象接口来实现 14 /// (把抽象实现的责任移到消费者的外部) 15 /// </summary> 16 public class NotificationSys1 17 { 18 private IEmailService svc; 19 public NotificationSys1() 20 { 21 svc = new EmailService1(); 22 } 23 public void InterestingEventHappened() 24 { 25 svc.SendMsg(); 26 } 27 }
2.把选择抽象实现的责任移到消费者类的外部。函数
控制反转(IOC)模式是抽象的;把依赖的建立移到使用这些的类的外部,这称为控制反转模式,之因此以这样命名,是由于反转的是依赖的建立,正由于如此,才消除消费类对依赖建立的控制。ui
依赖注入是另外一种控制反转模式形式,它没有像服务器定位器同样的中间对象。相反,组件以一种容许依赖的方式编写,一般由构造函数参数或属性设置器来显式表示。
spa
1. 构造函数注入设计
DI 的最多见形式是构造函数注入。该技术须要咱们为类建立一个显示表示因此依赖的构造函数。3d
1 /// <summary> 2 /// 构造注入 3 /// </summary> 4 public class NotificationSys 5 { 6 private IEmailService _svc; 7 8 public NotificationSys(IEmailService svc) 9 { 10 _svc =svc ; 11 } 12 public void InterestingEventHappened() 13 { 14 _svc.SendMsg(); 15 } 16 }
优势: 极大简化构造函数的实现;减小了NotificationSys类须要知道的信息量;需求的透明性,任何想建立NotificationSys类实例的代码都能查看构造函数,并精确的知道哪些内容是消费者必须的。rest
2.属性注入
属性注入是一种不太常见的依赖注入方式。顾名思义,该方式是经过设置对象上公共属性而不是经过使用构造函数参数来注入依赖。
public class NotificationSys { private IEmailService svc{get;set;} public void InterestingEventHappened() { svc.SendMsg(); } }
显而易见,这里咱们已经减小了需求的透明性,并且绝对比构造函数注入更容易产生错误。
选择属性注入缘由:
若是依赖在某种意义上是真正可选的,即在消费者类不提供依赖时,也有相应的处理,属性注入是个不错的选择
类的实例可能须要在咱们尚未控制调用的构造函数的状况下被建立
依赖注入容器是一个能够做为组件工厂使用的软件库,它能够自动检测和知足里面元素的依赖需求。常见的DI容器有 CastleWindsor,Unity,Autofac, ObjectBuilder,StructureMap,Spring.Net
路漫漫其修远兮, 吾将上下而求索