Castle IOC:Windsor (一)

前言

IOC,控制反转(Inversion of Control)的缩写,是一种优秀的设计模式。网上资料一大堆,也看了很多,但是我目前对 IOC 只理解出了一个作用:解耦

不同的平台,有不同的 IOC 模式的框架,像 Sun ONE 技术体系下的 Spring、Guice、Pico Container、Avalon、HiveMind、JBoss、Jdon、EJB。

像 .Net 技术体系下的 Spring.Net 、Autofac 等等。

这些我都没接触过。写出来纯属想装个逼。

我接触到的第一个 IOC 容器,就是 Castle 的 IOC 容器:Windsor。

IOC 的解耦到底是解了什么耦?怎么操作的? 下面写一个例子来回答我对这两个问题的理解。

一、引言

1,面向接口编程

为什么扯到面向接口编程,因为我觉得 IOC 就是把面向接口编程发挥到极致的工具

所以先看一个面向接口编程的例子:C# 接口的正确使用方式 。

在例子中,我们编写 Duplicator 类的时候,他的参数是接口,不必知道接口具体是怎么实现的,甚至不必知道实现接口的类的具体类名,直接把接口里面定义的方法拿来用就可以了:

如果要修改 IReader 或者 IWriter 实现里的代码, Duplicator 类可以不做任何改变,这很 “解耦”。

然后我们再看一下 Duplicator 的实例化对象 : duplicator,如下图所示,他的参数,是具体对象Reader 类是 IReader 的实现,HpWriter 类是 IWriter 的实现):

注意红色箭头标注的地方,也就是说在这里,Main 方法和具体对象耦合了。耦合是一个很讨人嫌的事,如果我们能够跟编写 Duplicator 类一样,用接口代替实例,那在这里不就实现解耦了嘛! 于是有了以下代码:

可以看到 visual studio 标出了很多错误,最关键的错误就是 “ “IReader” 是一个类型,这在给定的上下文中无效”。

在形参中,可以使用接口,但是在实参中,就不可以使用接口了。道理很简单,形参中,不是具体的类,不依赖具体的实现。但是在具体的类中,就要给出实现,不然编译器怎么知道这个接口的实现是哪个。

一般来说,这个耦合是解不开了。但是使用 IOC ,就可以解开这个耦合:

二、Windsor IOC 入门

在项目中引入 Windsor IOC,实现解耦:

1,右键 项目 -> 管理 NuGet 程序包,搜索 “castle.windsor”,不出意外的话应该就在搜索结果的第一个,点击安装。

2,安装之后,可能还要在 NuGet 里更新一下 Castle.Core。


3,引入 IOC 之后,就可以这么写了:

using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Interface_test.Implement;
using Interface_test.Interface;
using System;
namespace Interface_test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Input: ");
            //声明容器
            var contanier = new WindsorContainer();

            //注册接口和实现
            contanier.Register(Component.For<IReader>().ImplementedBy<Reader>());
            contanier.Register(Component.For<IWriter>().ImplementedBy<Writer>());

            Duplicator duplicator = new Duplicator();

            //1,直接耦合
            duplicator.Copy(new Reader(),new Writer());

            //2,从容器中取用对象
            duplicator.Copy(contanier.Resolve<IReader>(), contanier.Resolve<IWriter>());

            Console.ReadLine();
         }
    }
}

代码中,1 和 2 的效果一样,但是 2 中,是不是就没有写具体的实现呢。

IOC 的办法就是,先注册,告诉容器哪个接口对应哪个实现,然后在以后对实现的使用中,就可以直接写接口了,IOC 容器会帮我们取出合适的实现 “ 注入” 到实例里。实际上我们提前告诉了 IOC 哪个接口和哪个实现是绑定在一起的,所以叫 “依赖”。“依赖注入” 就是这么来的。

有人可能会说,引入 IOC 后,代码比之前复杂,还要提前注册接口和实现,这还不是耦合嘛。

没错,这确实是耦合,如果某个代码块和其他程序没有一点耦合,那这个代码块就可以直接删掉了。所以 IOC 并不是完全不耦合,而是弱化耦合,把耦合推迟,从开发阶段,推迟到配置阶段。

在实际的开发中,注册接口和实现的这部分代码,会写成配置文件,程序启动的时候加载配置文件,就知道接口和实现的对应关系了。如果要替换实现,只要修改配置文件就可以了。硬编码变成了软编码。

怎么把注册写到配置文件里,请参阅 Castle IOC:Windsor (二)

发表评论

Powered by WordPress | Theme Revised from Doo

苏ICP备18047621号

Copyright © 2017-2024 追光者博客