码迷,mamicode.com
首页 > 其他好文 > 详细

IoC和DI的理解

时间:2015-07-08 09:23:45      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:

1 概述

当我们想闭上眼睛想如何让我们的软件更加可用可维护时,我们总能想到一个词:松耦合。在这篇文章中,主要讲述了模块间存在的依赖关系,但这种依赖关系违背了依赖倒置原则。在这之后,我们将讨论一种解除软件依赖关系的设计模式——IoC,以及它的两种实现方法:依赖注入(DI)和服务定位。最后我们简单地列下当前流行的IoC容器工具。

目录

  • 依赖
  • 依赖倒置原则(DIP)
  • 控制反转IoC:解除两个模块间的直接依赖关系
  • 依赖注入(DI)
  • 服务定位(Service Locator)
  • IoC容器

2 依赖

当一个模块/类使用另一个模块/类,即存在了一种依赖关系。

技术分享

示例场景:

在这里,我们使用销售系统中保存订单的场景。比如,我们当前的需求是将数据保存到SQL Server中。在这里我们只关注业务层与数据持久层之间的依赖关系。

示例v1:

技术分享 View Code

3 依赖倒置原则(DIP)

在这个时候,当公司的牛XX业务人员将这个销售系统又卖给了另一家公司,大家都HAPPY。 但是对方公司唯一希望数据保存到ORACLE,因为他们其它的软件已经购买了ORACLE授权,并且不想再购买SQL SERVER授权。即软件需要支持数据库更换,我们应该如何解决

依赖倒置原则(DIP)

高层模块不应依赖于低层模块,两者应该依赖于抽象。

抽象不不应该依赖于实现,实现应该依赖于抽象。

 

上述示例v1中,OrderManager依赖于OrderDAL. 即高层模块(OrderManager)直接依赖于实现(OrderDAL), 而不是依赖于抽象。下面我们为数据持久层添加一层抽象,让业务层和数据持久实现层都依赖于抽象。

示例v2:

技术分享
技术分享
    public interface IOrderDAL
    {
        void Add();
    }

    public class OracleOrderDAL:IOrderDAL
    {
        public void Add()
        {
            Console.WriteLine("The order was added in into oracle database.");
        }
    }

    public class SQLServerOrderDAL:IOrderDAL
    {
        public void Add()
        {
            Console.WriteLine("The order was added in into sql server database.");
        }
    }

    public class OrderManager
    {
        public void AddOrder() 
        {
            IOrderDAL orderDAL = new OracleOrderDAL();
            orderDAL.Add();
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            OrderManager orderManager = new OrderManager();
            orderManager.AddOrder();

            Console.ReadLine();
        }
    }
技术分享

 

4 控制反转IoC

程序到这里,数据访问层已经添加一层抽象,即业务层和数据持久层都依赖于抽象。但是,注意这里,依然存在都依赖,即业务层依然要直接依赖于低层的数据持久实现层。当更换数据库时,会有很多这样的代码要更换。你知道我在说什么的..这还是太恶心…

文章到这里了,我们先说说控制反转——IoC(Inversion of Control), 网上关于IoC的解释很多,我比较喜欢这种http://www.cnblogs.com/liuhaorain/p/3747470.html:

它为相互依赖的组件提供抽象,将依赖(低层模块)对象的获得交给第三方(系统)来控制即依赖对象不在被依赖模块的类中直接通过new来获取

 

在多数情况下,上面的解释已经够用了,更广义一些的解释我认为是:

相对于过程式编程中,代码按顺序一步步执行,控制反转强调的是,将控制权交出,让第三方来控制程序的执行。

即除了将对象创建的工作交给第三方(我们主要关心的,如依赖注入和服务定位),IoC应该还包括将流程的控制转交出去,如事件,Callback 委托,观察者模式,异步等

在接下来的文章中,我们主要讨论依赖注入和服务定位。

5 依赖注入(DI)

依赖注入DI——Dependence Injection, 是一种IoC的实现方式。即将依赖对象的创建和绑定工作转移到第三者(调用方)。即 如果A对象依赖于B或C对象,那么就将B或C对象的创建工作转到A对象的调用方去。在上面示例中,将OracleOrderDAL或SQLServerOrderDAL的创建工作和绑定到IOrderDAL的工作转移到OrderManager的调用方中去,即具体对象创建的选择权移交到更高层的调用方法中。

依赖注入又分构造函数注入,属性注入和接口注入。我认为接口注入并不好用,所以这里只做构造函数和属性注入的示例。

5.1 构造函数注入

就是通过构造函数,传递依赖项。在这里,通过OrderManager的构造函数传入SQLServerOrderDAL或OracleOrderDAL

示例v3

技术分享
技术分享
    public class OrderManager
    {
        private IOrderDAL _orderDAL;

        public OrderManager(IOrderDAL orderDAL)
        {
            this._orderDAL = orderDAL;
        }

        public void AddOrder()
        {

            this._orderDAL.Add();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IOrderDAL orderDAL = new SQLServerOrderDAL();
            //IOrderDAL orderDAL = new OracleOrderDAL();
           
            OrderManager orderManager = new OrderManager(orderDAL);
            orderManager.AddOrder();

            Console.ReadLine();
        }
    }
技术分享

5.2 属性注入

即通过属性传入依赖项。在这里,能过OrderManager的OrderDA属性项,传入SQLServerOrderDAL或OracleOrderDAL

示例4

技术分享
技术分享
    public class OrderManager
    {
        private IOrderDAL _orderDAL;

        public IOrderDAL OrderDAL 
        {
            set { this._orderDAL = value; }
            get { return this._orderDAL; }
        }

        public void AddOrder() 
        {

            this._orderDAL.Add();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IOrderDAL orderDAL = new SQLServerOrderDAL();
            //IOrderDAL orderDAL = new OracleOrderDAL();
           
            OrderManager orderManager = new OrderManager();
            orderManager.OrderDAL = orderDAL;
            orderManager.AddOrder();

            Console.ReadLine();
        }
    }
技术分享

6 服务定位(Service Locator)

服务定位SL——Service Locator, 也是一种IoC的实现方式。即将依赖对象的创建和绑定工作转移到第三者(另一个模块)。即 如果A对象依赖于B或C对象,那么就将B或C对象的创建工作转到F对象中去。在上面示例中,将OracleOrderDAL或SQLServerOrderDAL的创建工作和绑定到IOrderDAL的工作转移到Factory中去, 即具体对象的创建选择权移交给Factory中。

示例v5

技术分享
技术分享
    public class Factory
    {
        public static IOrderDAL GetOrderDAL() 
        {
            //string type = "SQLServer";
            string type = "Oracle";
            string assemblyName = string.Format("v5_{0}DAL",type);
            string typeName = string.Format("{0}.{1}OrderDAL",assemblyName,type);
            return (IOrderDAL)Assembly.Load(assemblyName).CreateInstance(typeName);
        }
    }

    public class OrderManager
    {
        public void AddOrder() 
        {
            IOrderDAL orderDAL = Factory.GetOrderDAL();
            orderDAL.Add();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            OrderManager orderManager = new OrderManager();
            orderManager.AddOrder();

            Console.ReadLine();
        }
    }
技术分享

7 IoC容器

下面是一些主流的IoC容器工具以供参考

1. Unity:  http://unity.codeplex.com/

2. Ninject:  http://www.ninject.org/

3. Autofac:  http://code.google.com/p/autofac/

4. Spring.NET: http://www.springframework.net/

Unity示例v6

技术分享
技术分享
    public class OrderManager
    {
        private IOrderDAL _orderDAL;

        public OrderManager(IOrderDAL orderDAL)
        {
            this._orderDAL = orderDAL;
        }

        public void AddOrder()
        {

            this._orderDAL.Add();
        }
    }

    class Program
    {
        
        static void Main(string[] args)
        {
            UnityContainer container = new UnityContainer();
            //container.RegisterType<IOrderDAL, SQLServerOrderDAL>();
            container.RegisterType<IOrderDAL, OracleOrderDAL>();

            OrderManager orderManager = container.Resolve<OrderManager>();
            orderManager.AddOrder();

            Console.ReadLine();
        }
    }
技术分享

上面是一些我关于IoC和DI的理解,如有不对的地方,欢迎提出讨论。

 

IoC和DI的理解

标签:

原文地址:http://www.cnblogs.com/wyBlog117/p/4629141.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!