原文: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;

C#依赖注入控制反转IOC实现详解的更多相关文章

  1. Helloworld之Spring依赖注入/控制反转(DI/IoC)版

    Helloworld之Spring依赖注入/控制反转(DI/IoC)版 作者:雨水, 日期:2014-10-29 摘要:本文主要用于培训刚開始学习的人理解Spring中的依赖注入的基本概念. 先介绍依 ...

  2. PHP关于依赖注入(控制反转)的解释和例子说明

    PHP关于依赖注入(控制反转)的解释和例子说明 发表于2年前(2014-03-20 10:12)   阅读(726) | 评论(1) 8人收藏此文章, 我要收藏 赞2 阿里云双11绽放在即 1111 ...

  3. Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

    原文地址:http://blog.csdn.net/wangyang1354/article/details/50757098 我们经常会遇到这样一种情景,就是在我们开发项目的时候经常会在一个类中调用 ...

  4. Benefits of Using the Spring Framework Dependency Injection 依赖注入 控制反转

    小结: 1. Dependency Injection is merely one concrete example of Inversion of Control. 依赖注入是仅仅是控制反转的一个具 ...

  5. laravel5.2总结--服务容器(依赖注入,控制反转)

    1.依赖 我们定义两个类:class Supperman 和 class Power,现在我们要使用Supperman ,而Supperman 依赖了Power class Supperman { p ...

  6. 依赖注入&控制反转

    IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 要想理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁? 依赖:谁依 ...

  7. Spring 依赖注入控制反转实现,及编码解析(自制容器)

    定义: 在运行期,由外部容器动态的将依赖对象动态地注入到组件中. 两种方式: 手工装配 -set方式 -构造器 -注解方式 自动装配(不推荐) 1利用构造器 2set方法注入 dao: package ...

  8. 【半小时大话.net依赖注入】(下)详解AutoFac+实战Mvc、Api以及.NET Core的依赖注入

    系列目录 上|理论基础+实战控制台程序实现AutoFac注入 下|详解AutoFac+实战Mvc.Api以及.NET Core的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...

  9. MVC 依赖注入/控制反转

    http://www.cnblogs.com/cnmaxu/archive/2010/10/12/1848735.html http://www.cnblogs.com/artech/archive/ ...

随机推荐

  1. sshfs 通过ssh 挂载远程目录

    安装:yum -y install sshfs 挂载远程 ssh 文件系统: sshfs -p 1234 root@192.168.1.218:/home/ /mnt/ sshfs -p SSH端口 ...

  2. 异步FIFO设计

    参考http://www.cnblogs.com/BitArt/archive/2013/04/10/3010073.html http://blog.sina.com.cn/s/blog_6d30f ...

  3. [arm]虚拟机,2440开发板,主机三者互通

    想实现3着互通先必须保证三者的网段是相同的: 首先查看电脑主机的IP: 然后再看看虚拟机的IP: 惊喜的发现,他们在一个网段上---那就不用改了-- 再去看看开发板上的IP: 这里注意,输入命令时,是 ...

  4. dp hdu5653 xiaoxin and his watermelon candy

    传送门:点击打开链接 题意:有n个箱子排成一排,有m个炸弹.位置告诉你.如今炸弹的左边伤害和右边伤害能够自己控制,要求 每一个炸弹炸的箱子数的累乘,输出答案取log2并乘以1e6 思路:直接2for ...

  5. HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

    HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意:  给一个序列由 ...

  6. 自定义 matplotlib 设置

    Customizing plots with style sheets import matplotlib as mpl 查看配置文件所在的目录:mpl.get_configdir() 1. 自定义 ...

  7. error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

    rsguo:SECONDARY> db.users.find();error: { "$err" : "not master and slaveOk=false&q ...

  8. angular模块详解

    原文: https://www.jianshu.com/p/819421ff955a 大纲 1.angular应用是模块化的 2.对模块(Module)的认识 3.模块的分类:根模块和特性模块 4.N ...

  9. Node.js v10.1.0 Documentation

    Modules Stable 在 Node.js 模块系统中,每个文件都会被当做一个独立的模块.假设有一个名为 foo.js: const circle = require('./circle.js' ...

  10. [Recompose] Transform Props using Recompose --mapProps

    Learn how to use the 'mapProps' higher-order component to modify an existing component’s API (its pr ...