第13章 依赖注入
一、 软件设计模式为更好地理解依赖注入的概念,以及如何将其应用于MVC程序中,首先了解一下软件设计模式是很有必要的。1 、设计模式——控制反转模式 代码如下: public class EmailService { public void SendMessage() { } } //NotificationSystem类依赖于EmailService类。 //当一个组件依赖于其他组件时,我们称其为耦合。 //通知系统(NotificationSystem)在其构造函数内部直接创建e-mail服务的一个实例 //通知系统精确地知道创建和使用了哪种类型服务(高耦合) //当修改一个类(EmailService)很可能破坏依赖于它的另一个类(NotificationSystem) public class NotificationSystem { private EmailService svc; public NotificationSystem() { svc = new EmailService(); } public void InterestingEnentHappened() { svc.SendMessage(); } }上面代码设计存在一个问题:系统管理员想得到文本信息而不是电子邮件。 为降低组件之间的耦合程度,一般采取两个独立单相关的步骤: (1)在两块代码之间引用抽象层 通常使用接口(或抽象类)来代表两个类之间的抽象层。 我们引用一个接口来代表抽象层,并确保编写的代码只调用接口中的方法和属性。 这样一来,NotificationSystem类中的私有副本就变成接口的一个实例,而不再是具体类型,并且构造函数隐藏了时间类型。 代码如下: public interface IMessagingService { void SendMessage(); } public class EmailService:IMessagingService { public void SendMessage() { } } public class NotificationSystem { private IMessagingService svc; public NotificationSystem() { svc = new EmailService(); } public void InterestingEnentHappened() { svc.SendMessage(); } } (2)、把选择抽象实现的责任移到消费类的外部。 把 EmailService类的创建移到NotificationSystem类的外面。 控制反转模式是抽象的,它只是表述应该从消费者类中移除依赖创建,而没有表述如何实现。 用控制反转模式实现责任转移的两种常用方法:服务定位器和依赖注入。 2、 设计模式——服务定位器 (1)、强类型服务定位器 //服务定位器(已经预先知道IMessagingService类型对象) public interface IServiceLocator { IMessagingService GetMessagingService(); } public interface IMessagingService { void SendMessage(); } public class EmailService:IMessagingService { public void SendMessage() { } } public class NotificationSystem { private IMessagingService svc; public NotificationSystem(IServiceLocator locator) { svc = locator.GetMessagingService(); } public void InterestingEnentHappened() { svc.SendMessage(); } } (2)、弱类型服务定位器 //弱类型服务定位器,它允许请求任意服务类型 public interface IServiceLocator { //Object版本的GetService Object GetService(Type serviceType); ////从.NET 2.0引入泛型以来,出现泛型版本GetService //TService GetService<TService>(); } //IServiceLocator扩展方法 public static class ServiceLocatorExtensions { public static TService GetService<TService>(this IServiceLocator locator) { return (TService)locator.GetService(typeof(TService)); } } public interface IMessagingService { void SendMessage(); } public class EmailService:IMessagingService { public void SendMessage() { } } public class NotificationSystem { private IMessagingService svc; public NotificationSystem(IServiceLocator locator) { svc = (IMessagingService)locator.GetService(typeof(IMessagingService));//Object版本 svc = locator.GetService<IMessagingService>();//泛型版本 } public void InterestingEnentHappened() { svc.SendMessage(); } } 服务定位器的用法比较简单:我们先从某个地方得到服务定位器,然后利用定位器查询依赖。 组件需求的不透明性,促使我们选择下一个反转控制模式:依赖注入 3 、设计模式—— 依赖注入 //服务接口 public interface IMessagingService { void SendMessage(); } //邮件服务 public class EmailService:IMessagingService { public void SendMessage() { } } (1)、构造函数注入 //通知系统 public class NotificationSystem { private IMessagingService svc; //构造函数中实现 IMessagingService 接口实例 public NotificationSystem(IMessagingService service) { this.svc = service; } public void InterestingEnentHappened() { svc.SendMessage(); } }(2)、属性依赖注入 通过对象上的公共属性来注入依赖。 public class NotificationSystem { public IMessagingService MessagingService { get; set; } public void InterestingEnentHappened() { if (MessagingService == null) { throw new InvalidOperationException("先设置MessagingService"); } MessagingService.SendMessage(); } } 二、 MVC中的依赖解析在ASP.NET MVC中的应用 1、 MVC中的单一注册服务 用户为MVC使用的服务能且仅能注册一个服务实例,此类服务称为单一注册服务,用来从解析器中检索单一注册服务的方法是GetService. 2 、MVC中的复合注册服务 可以注册多个服务实例的服务。我们可以使用GetServices方法从解析器中检索复合注册服务。 ASP.NET MVC支持两个复合服务模型: 3 、MVC中的任意对象 MVC中有两个特殊的情形。在这两个情形中,MVC框架请求一个依赖解析器来创建任意对象, 这些创建的对象严格来说不是服务,而是控制器和视图页面。 (1)、创建控制器 将控制器名称映射为类型以及将类型实例化为对象。 public interface IControllerActivator { } 三、 Web API中的依赖解析 1、 Web API中的单一注册服务 2 、Web API中的复合注册服务 3 、Web API中的任意对象 4、 对比MVC和Web API中的依赖解析器 四、 小结(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |