• C#依赖注入控制反转IOC实现详解


    IOC的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。

    举个例子,组件A中有类ClassA,组件B中有接口IB和其对应的实现类B1和B2。

    那么,现在ClassA需要利用IB接口来做一些事情,例如:

    public class ClassA {
    public void DoSomething() {
    IB b = ???
    b.DoWork();
    }
    }

    现在的问题来了,IB b = ??? 中这三个???要写什么代码?是要写成 IB b = new B1(),还是要写成IB b = new B2() ?

    不管是哪一种,都会让ClassA强依赖于IB的实现。

    在上面这种方案中,ClassA通过new一个B1或B2来实现对IB的依赖的获取,换句话说,ClassA在主动获取依赖。

    这样的设计会让ClassA很难扩展,那我们要改良设计:使用依赖注入。上面说到了,问题出在new这里,也就是依赖是Class去主动获取的,那我们就要解决这个问题:不要去主动获取对IB的依赖(通过new),而让这个依赖从ClassA的外面“注入”进来。注入有多种方式,比较常用的一种是通过构造函数注入,那么,我们要把ClassA改成:

    public class ClassA {
    private IB b;

    public ClassA(IB b) {
    this.b = b;
    }

    public DoSomething() {
    this.b.DoWork();
    }
    }

    可以看到,通过把IB这个依赖从构造函数中“注”进来后,ClassA就不依赖IB的实现了。还可以发现,这个重构过程中,我们是把"ClassA主动获取对IB的依赖”变成“把对IB的依赖从外部注入到ClassA中”,依赖的方向反转了,所以,依赖注入又称“控制反转”。

    IoC框架(如Unity, Autofac,Spring.Net),其中Unity是微软自己封装的,另外可以利用Extnesions.Dependency动态生成类(参考之前的将RFCTable转为List<T>利用依赖注入动态生成类的例子),参考之前的代码

    下面以Unity作为介绍:

    Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题。构建一个成功应用程序的关键是实现非常松散的耦合设计。下面介绍一下c#中使用unity的方法(我是以webapi项目为例,但本例中并没有针对webapi做特殊处理)

    新建一个mvc4 webapi项目,下面的例子只用到get方法

    用nuget安装unity,如图

    新建一个接口类,以及继承该接口的两个类

    直接在api/values的get中尝试简单实现unity

    using (IUnityContainer container = new UnityContainer())

                {

                    container.RegisterType<IBook, BBook>();

                    IBook a = container.Resolve<IBook>();

                    var strResult = a.Write();

                    return strResult;

                }  

    然后在浏览器中查看,页面显示的返回值,是BBook的

    如果container.RegisterType<IBook, BBook>();中的BBook改为ABook,返回值就是ABook的内容

    config中代码如下

    在configSections中加入

    <section name="unity"

    type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

    在configuration中加入

    <unity  xmlns="http://schemas.microsoft.com/practices/2010/unity">

        <container>

          <register type="testunity.Models.IBook,testunity" mapTo="testunity.Models.ABook, testunity" />

        </container>

      </unity>

    注意 type="testunity.Models.IBook,testunity" mapTo="testunity.Models.ABook, testunity" 

    testunity.Models.IBook是命名空间加类名

    testunity是程序集的名称

    然后cs的代码改成

    using (IUnityContainer container = new UnityContainer())

    {

        UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

        configuration.Configure(container);

        IBook a = container.Resolve<IBook>();

        var strResult = a.Write();

        return strResult;

    }   

    在浏览器中可以看到返回结果对应的是config中register的那个类

    每次调用都要写IUnityContainer container = new UnityContainer()显然不是好办法

    那就把container封装到一个单列类中

    简单实现如下

    public class ServiceLocator:IServiceProvider

        {

            private readonly IUnityContainer _container;

            private static readonly ServiceLocator instance = new ServiceLocator();

            private ServiceLocator()

            {

                UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

                _container = new UnityContainer();

                section.Configure(_container);

            }

            public static ServiceLocator Instance

            {

                get { return instance; }

            }

            public object GetService(Type serviceType)

            {

                return _container.Resolve(serviceType);

            }

            public T GetService<T>()

            {

                return _container.Resolve<T>();

            }

        }

    cs代码修改如下

    IBook a = ServiceLocator.Instance.GetService<IBook>();

    var strResult = a.Write();

    return strResult;

  • 相关阅读:
    范围截取 字符串内容
    post请求 application/x‐www‐form‐urlencoded
    未能加载文件或程序集“Newtonsoft.Json”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
    获取Url链接后的问号传值中的参数
    Post 提交跳转页面 Jquery请求
    C# POST application/x-www-form-urlencoded 请求
    《exception》第九次团队作业:Beta冲刺与验收准备(大结局)
    《Exception》第八次团队作业:Alpha冲刺
    《Exception团队》第七次作业:团队项目设计完善&编码
    《Exceptioning团队》第六次作业:团队项目系统设计改进与详细设计
  • 原文地址:https://www.cnblogs.com/happyShare/p/8922905.html
Copyright © 2020-2023  润新知