夜寒露重,伊人珍重!  
.net灌水区

最近在学习IOC的东西,顺便写点加深自己的理解。。。

1.什么是IOC(Inversion of control-控制反转)

   Iocinversion of control)的翻译为控制反转。这个概念其实并不新奇,在程序开发的各个环节你都有意或无意的使用到了。

   控制反转顾名思义是指在程序执行时控制权的转移,比如一个控制台程序如:

    

       using System;

       using System.Collections.Generic;

       using System.Text;

 

       namespace ConsoleApplication1

       {

          class Program

            {

               static void Main(string[] args)

                {

                   Console.Write("Please Input Some Words:");

                   string inputData = Console.ReadLine();

                   Console.WriteLine(inputData);

                   Console.Read();

                 }

            }

        }

  

      该控制台程序的开始执行后,OS就将控制权交给程序直到运行结束,在这个过程里所有的控制权都在程序里,这就是控制。那什么是控制反转呢?我们看一个form程序:

   

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsApplication10

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            MessageBox.Show(textBox1.Text);

        }

    }

}

 

这个程序在运行开始时经过Application.Run 函数后将控制权交给了Windows Forms Framework框架,进入等待信息的状态,直到用户点击button1按钮,Windows Forms Framework框架或得点击信息后会调用 button1_Click()函数内的代码,此时控制权又从Windows Forms Framework框架转到了应用程序。这就是控制反转,主程序的控制权转移到了Windows Forms Framework框架。

2.IOC和依赖注入(Dependency Injection)的关系

       IOC的中心思想在于控制反转,这个概念在dotnet Framework里非常常见,但是为什么这两年会引起如此多的讨论呢?Castle/srping.net/Avalon/picocontainer/objectspace等等Ioc项目又想达到什么样的目的呢?

       Windows Forms FrameworkCastle都反转了一部分控制权在自己身上,不同的是:Windows Forms Framework将主程序的控制权反转到自己身上;Castle将对象的配置、建立、释放等控制权转移到自己身上。两者都符合控制反转的理念,但是其初衷和目的都不相同,为了区别这两者,設計大師Martin Fowlercastle类型的IOC框架创造了一个名词:Dependency Injection(依赖注入)。

3.我们为什么需要依赖注入

       依赖注入的目的是要尽量消除对象之间的依赖性,减少对象的耦合程度。但是为什么我们要消除这些依赖呢?假如我们有这样一个场景:编写一个程序需要记录运行日志,我们也许会这样写:

            //主程序

                     class Program

            {

               static void Main(string[] args)

                {

                   Console.Write("Please Input Some Words:");

                   string inputData = Console.ReadLine();

                   ILogger logger=new LoggerA();

                   Logger.write(inputData);

                 }

            }

 

           

 

            //记录类接口

            Public interface ILogger

{

    Public void wirtelog(string message)

}

 

 

//记录类的一个实现

Class LoggerAILogger

{

    Public void writelog(string message)

{

       ……..

}

             }

 

这个程序是基于Interface Base Programming概念来编写,这样做是为了降低program类和LoggerA的耦合关系,其实他们之间本来也没有什么耦合关系,但是由于program类使用了“ ILogger logger=new LoggerA()”来获取LoggerA的实例却使得Program类既依赖于ILogger接口也依赖于LoggerA类。我们设计的目的当然是希望Program类只依赖于ILogger接口了,但是我们如何获取实现了ILogger接口的实例(如LoggerA)呢?

在现实中这种情况还有一个名称叫:插件。我们希望Program类能够与任何事项实现了ILogger接口的类配合工作,并且允许在运行期插入具体的实现类,插入行为完全脱离Program编写者的控制,不需要重新编译Prorgram,现在的问题就集中在如何设计这个连接过程,然Program在不知道ILogger的具体实现的情况下与其协同工作。而解决这个问题的方法就可以使用IOC(控制反转),使用一个 IOC框架类来管理对象的配置、生成、释放等,程序只与IOC类进行交互来获取对象。

当然IOC框架是如何实现IOC的就需要自己慢慢研究了。

4.依赖注入的实现方式

目前依赖注入的实现方式主要有3中:构造注入、设值注入和接口注入。

种种方法都是为了降低对象之间的依赖性,但并不能消除对象之间的依赖,只是将这种依赖降到最小或者推迟依赖发生的时间(编译前依赖还是编译后依赖(插件)),甚至将其依赖性用配置文件分离出来。

为了说明几种注入方式的区别,我们假设有一个类A,还有一个类B,类B是实现IB这个接口的:

构造子注入:在类A的构造函数里出入一个参数,就是类B的实例。

设置注入:A有一个只写属性,就是类B

接口注入:类A接受一个IB接口的参数。

这个介绍有点简单,不过确实没什么说的,具体的可以看看設計大師Martin Fowler的文章。

5.服务定位器和依赖注入

提到了依赖注入还是说说服务定位(service locator),服务定位同样可以达到和依赖注入一样的效果:消除对具体实现类的依赖,但是程序会依赖于服务定位器。服务定位器仅仅管理单独的对象创建等,而对象间的关系还是由程序处理,当然你使用代码管理还是配置文件视乎你的设计。而依赖注入则不经管理了对象的创建,还管理对象之间的依赖。

 

 

以上都是一家之言,不正确的地方请拍砖。。。。。呵呵

posted on 2007-01-08 17:04  大非国  阅读(5008)  评论(18编辑  收藏  举报