讲到IOC容器,就必须提到DIP(依赖倒置原则)。

DIP是OOD(面向对象设计)的一个重要思想,在该原则上引申出了\IOC(控制反转)\DI(依赖注入)\IOC容器。

居然讲到IOC容器,当然我们要先了解DIP。

我们来看下定义:

依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)。

控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)。

依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)。

IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)。

 

DIP依赖倒置原则

什么是原则?

答:代表性则问题性的一个定点词 行事所依据的准则

DIP仅仅只是代表依赖倒置的一个依据准则而已。DIP是一种 软件设计原则,它仅仅告诉你两个模块之间应该如何依赖,但是它并没有告诉如何做。

DIP倡导高层模块定义了接口,将不再直接依赖于低层模块,低层模块负责实现高层模块定义的接口。这样,当有新的低层模块实现时,不需要修改高层模块的代码。

由此,我们可以总结出使用DIP的优点:

  • 可以修改一部分代码而不影响其他模块。
  • 可以修改一部分代码而不会让系统崩溃。
  • 组件松耦合,且可复用,提高开发效率。

博客园里很多人用了ATM机的生活例子来进行讲解,ATM机为高层,底层为银行卡,DIP的准则告诉我们ATM机来定义接口然后让银行卡来实现。这样的好处ATM机可以支持很多种银行卡。

IOC控制反转

IOC是什么呢?

IoC则是一种 软件设计模式,它告诉你应该如何做,来解除相互依赖模块的耦合。

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

IoC有两种方式:依赖注入和服务定位

这里就讲到依赖注入DI

DI依赖注入

DI就是将依赖对象的创建和绑定转移到被依赖对象类的外部来实现,将需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象。

注入的方式有构造函数、属性、接口。

我们来看下构造函数注入例子:

先定义一个数据库操作方法接口

  • public interface ILinkmethod

    {

            void Add();

    }

    新增一个实现类

    public class SqlServerDal: ILinkmethod

    {

           public void Add()

           {

               Console.WriteLine("在数据库中添加一条订单!");

           }

    }

    public class ActionOrder

      {

            private ILinkmethod _ida;//定义一个私有变量保存抽象

     
     

            //构造函数注入

            public Order(ILinkmethod ida)

            {

                _ida = ida;//传递依赖

          }

     
     

            public void Add()

            {

                _ida.Add();

            }

    }

    调用:

     static void Main(string[] args)

            {

                SqlServerDal dal = new SqlServerDal();//在外部创建依赖对象

                Order order = new Order(dal);//通过构造函数注入依赖

     
     

                order.Add();

     
     

                Console.Read();

            }

    上面的基础铺垫后终于到我们的主题了:

    IOC容器

    IoC容器实际上是一个DI框架, 它能简化我们的工作量。它包含以下几个功能:

    动态创建、注入依赖对象。

    管理对象生命周期。

    映射依赖关系。

    比较流行的Ioc容器:

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

2. Castle Windsor:  http://www.castleproject.org/container/index.html

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

4. StructureMap: http://docs.structuremap.net/

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

注:根据园友 徐少侠 的提醒,MEF不应该是IoC容器。我又查阅了一些资料,觉得MEF作为IoC容器是有点勉强,它的主要作用还是用于应用程序扩展,避免生成脆弱的硬依赖项。

 6. MEF:  http://msdn.microsoft.com/zh-cn/library/dd460648.aspx 

另外,园友 aixuexi 提出Spring.NET也是比较流行的IoC容器。

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

园友 wdwwtzy 也推荐了一个不错的IoC容器:

8. LightInject:  http://www.lightinject.net/ (推荐使用Chrome浏览器访问)

以上IOC容器摘抄于木小楠整理。

我们下面来中间讲解下Autofac,为了让大家更加容易入手,请先了解上述内容

Autofac是一款IOC框架,比较于其他的IOC框架,如Spring.NET,Unity,Castle等等所包含的,它很轻量级性能上非常高。

我们来看下官方解释:

Adding Components

Components are registered with a ContainerBuilder:

var builder = new ContainerBuilder();

Autofac can use a Linq expression, a .NET type, or a pre-built instance as a component:

builder.Register(c => new TaskController(c.Resolve<ITaskRepository>()));

 

builder.RegisterType<TaskController>();

 

builder.RegisterInstance(new TaskController());

Or, Autofac can find and register the component types in an assembly:

builder.RegisterAssemblyTypes(controllerAssembly);

Calling Build() creates a container:

var container = builder.Build();

To retrieve a component instance from a container, a service is requested. By default, components provide their concrete type as a service:

var taskController = container.Resolve<TaskController>();

To specify that the component's service is an interface, the As() method is used at registration time:

builder.RegisterType<TaskController>().As<IController>();

// enabling

var taskController = container.Resolve<IController>();

 

方法1:

var builder = new ContainerBuilder();

builder.RegisterType<TestService>();

builder.RegisterType<TestDao>().As<ITestDao>();

return builder.Build();

方法二:

为了统一管理 IoC 相关的代码,并避免在底层类库中到处引用 Autofac 这个第三方组件,定义了一个专门用于管理需要依赖注入的接口与实现类的空接口 IDependency:

 

/// <summary>

/// 依赖注入接口,表示该接口的实现类将自动注册到IoC容器中

/// </summary>

public interface IDependency

{ }

 

这个接口没有任何方法,不会对系统的业务逻辑造成污染,所有需要进行依赖注入的接口,都要继承这个空接口,例如:

业务单元操作接口:

 

/// <summary>

/// 业务单元操作接口

/// </summary>

public interface IUnitOfWork : IDependency

{

...

}

 

Autofac 是支持批量子类注册的,有了 IDependency 这个基接口,我们只需要 Global 中很简单的几行代码,就可以完成整个系统的依赖注入匹配:

 

ContainerBuilder builder = new ContainerBuilder();

builder.RegisterGeneric(typeof(Repository<,>)).As(typeof(IRepository<,>));

Type baseType = typeof(IDependency);

 

// 获取所有相关类库的程序集

Assembly[] assemblies = ...

 

builder.RegisterAssemblyTypes(assemblies)

.Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)

.AsImplementedInterfaces().InstancePerLifetimeScope();//InstancePerLifetimeScope 保证对象生命周期基于请求

IContainer container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

IOC容器之Autofac的更多相关文章

  1. spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory

    1. Spring的IoC容器和IoC Service Provider的关系 Spring的IoC容器和IoC Service Provider所提供的服务之间存在一定的交集,二者的关系如图4-1所 ...

  2. IoC容器之Unity

    关于IoC.Unity见博友文章点击这里. 话不多说,上程序HelloUnity,程序采用VS2010,Unity2.1. 1.程序框架如下 2.类库HelloUnity.Objects,主要为实体类 ...

  3. Spring 的IOC容器之XML方式

    1. Spring 入门 1.1 概述 Spring 是一个分层的 JavaEE 轻量级开源框架; Spring 的核心是控制反转(IOC)和面向切面(AOP); 1.2 特点 方便解耦,简化开发; ...

  4. 【spring源码学习】spring的IOC容器之BeanFactoryPostProcessor接口学习

    [一]org.springframework.beans.factory.config.BeanFactoryPostProcessor接口==>该接口实现方法的执行时机:该接口void pos ...

  5. 【spring源码学习】Spring的IOC容器之BeanPostProcessor接口学习

    一:含义作用 ==>BeanPostProcessor接口是众多Spring提供给开发者的bean生命周期内自定义逻辑拓展接口中的一个 二:接口定义 package org.springfram ...

  6. spring揭秘读书笔记----spring的ioc容器之BeanFactory

    spring的ioc容器是一种特殊的Ioc Service Provider(ioc服务提供者),如果把普通的ioc容器认为是工厂模式(其实很相似),那spring的ioc容器只是让这个工厂的功能更强 ...

  7. Spring源码解析02:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  8. Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  9. Java并发编程:并发容器之CopyOnWriteArrayList(转载)

    Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...

随机推荐

  1. 第7课 Qt中的坐标系统

    1. 坐标系统 (1)GUI操作系统都有特定的坐标系统 (2)图形界面程序在坐标系统中进行窗口和部件的定位 (3)定位类型 ①顶级窗口部件的定位 ②窗口内部件的定位 ③窗口部件的大小设置 (4)QWi ...

  2. sqlplus rlwrap readline

  3. java 在MySQL中存储文件,读取文件(包括图片,word文档,excel表格,ppt,zip文件等)

    转自:https://blog.csdn.net/u014475796/article/details/49893261 在设计到数据库的开发中,难免要将图片或文档文件(如word)插入到数据库中的情 ...

  4. python中numpy计算数组的行列式numpy.linalg.det()

    numpy.linalg.det numpy.linalg.det(a)[source] 计算任何一个数组a的行列式,但是这里要求数组的最后两个维度必须是方阵. 参数: a : (..., M, M) ...

  5. HBase安装和启动

    目录 认识HBase 前期准备 1. 解压HBase 2. 修改3个配置文件(配置文件目录:hbase-0.96.2-hadoop2/conf/) 3. 将hadoop的hdfs-site.xml和c ...

  6. 新手C#异常的学习2018.08.07

    异常是在程序执行期间出现的问题.C# 中的异常是对程序运行时出现的特殊情况的一种响应,比如尝试除以零. class Program { static void Main(string[] args) ...

  7. 数据库帮助类 SqlServerHelp

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  8. 面试概率极大的Oracle存储过程

    1.什么是存储过程.存储过程是数据库服务器端的一段程序,它有两种类型.一种类似于SELECT查询,用于检索数据,检索到的数据能够以数据集的形式返回给客户.另一种类似于INSERT或DELETE查询,它 ...

  9. Redis开发、管理实战

    一.数据类型 String : 字符类型 Hash: 字典类型 List: 列表 Set: 集合 Sorted set: 有序集合 二.全局Key操作 KEYS * 查看KEY支持通配符 DEL 删除 ...

  10. Linux运维实战之DNS(bind)服务器的安装与配置

    转自http://sweetpotato.blog.51cto.com/533893/1598225 上次博文我们讨论了DNS的基础,本次博文我们重点来看看如何配置一台DNS服务器. [本次博文的主要 ...