第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中的依赖解析  1、 MVC中的单一注册服务  2 、MVC中的复合注册服务 3 、MVC中的任意对象  三、 Web API中的依赖解析 1、 Web API中的单一注册服务 2 、Web API中的复合注册服务  3 、Web API中的任意对象 4、 对比MVC和Web API中的依赖解析器 四、 小结

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...