IOC容器之Autofac
讲到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容器:
- 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:
/// 依赖注入接口,表示该接口的实现类将自动注册到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的更多相关文章
- spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory
1. Spring的IoC容器和IoC Service Provider的关系 Spring的IoC容器和IoC Service Provider所提供的服务之间存在一定的交集,二者的关系如图4-1所 ...
- IoC容器之Unity
关于IoC.Unity见博友文章点击这里. 话不多说,上程序HelloUnity,程序采用VS2010,Unity2.1. 1.程序框架如下 2.类库HelloUnity.Objects,主要为实体类 ...
- Spring 的IOC容器之XML方式
1. Spring 入门 1.1 概述 Spring 是一个分层的 JavaEE 轻量级开源框架; Spring 的核心是控制反转(IOC)和面向切面(AOP); 1.2 特点 方便解耦,简化开发; ...
- 【spring源码学习】spring的IOC容器之BeanFactoryPostProcessor接口学习
[一]org.springframework.beans.factory.config.BeanFactoryPostProcessor接口==>该接口实现方法的执行时机:该接口void pos ...
- 【spring源码学习】Spring的IOC容器之BeanPostProcessor接口学习
一:含义作用 ==>BeanPostProcessor接口是众多Spring提供给开发者的bean生命周期内自定义逻辑拓展接口中的一个 二:接口定义 package org.springfram ...
- spring揭秘读书笔记----spring的ioc容器之BeanFactory
spring的ioc容器是一种特殊的Ioc Service Provider(ioc服务提供者),如果把普通的ioc容器认为是工厂模式(其实很相似),那spring的ioc容器只是让这个工厂的功能更强 ...
- Spring源码解析02:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
- Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
- Java并发编程:并发容器之CopyOnWriteArrayList(转载)
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
随机推荐
- RabbitMQ 信道(channel)挂掉,但连接仍然存在,同时出现错误:Received remote Channel.Close (406): PRECONDITION_FAILED - unknown delivery tag x 的问题
该问题经过一番试验,发现是消费者(consumer)程序逻辑错误导致:在消息处理的回调函数中多次ack或nack. 开启Python日志,并在回调函数中两次ack得到如下信息: F:\software ...
- django-上下文渲染器,将后端内容提供给模板使用,自定义渲染器
使用场景:当同一个类容需要出现在多个模板中, 上下文管理器就是将这个内容以字典的形式返回给所有模板,模板通过 {{ key }}取值. 结构:上下文管理器 文件名一般为context_processo ...
- 3_bootsrap布局容器
3.布局容器 BootStrap必须需要至少一个布局容器,才能为页面内容进行封装和方便的样式控制. 相当于一个画板. 帮助手册位置:全局CSS样式------->概览------->布局容 ...
- Django学习---Form组件认证
Form组件认证 能够帮助我们做用户认证. 以前写我们自己写用户认证的时候,我们自己写HTML的form表单,点击提交,数据就被发送到后台,后台进行验证.在验证过程中我们就需要自己去写正则表达式去匹配 ...
- 利用iWARP/RDMA解决以太网高延迟
导读:“iWARP能够带来超低延迟.”据介绍,RDMA,即远程直接内存访问提供了应用程序到应用程序的直接通信能力,这也就意味着,应用将跳过操作系统,实现远程内存应用程序的访问 关键词: iWARP 低 ...
- android 学习 之 布局(上)
学习安卓布局前,先了解三个属性值: 1.fill_parent: 设置一个构件的布局为fill_parent将强制性地使构件扩展,以填充布局单元内尽可能多的空间 2.match_parent: And ...
- jeesite快速开发平台(六)----代码生成模块介绍及使用
转自:https://blog.csdn.net/u011781521/article/details/79309861
- CLR如何控制类型中的字段排序
[StructLayout(LayoutKind.Sequential) ]保持字段布局 [StructLayout(LayoutKind.Auto) ]CLR自动选择最优 [StructLayout ...
- C# 与 Java Rsa加密与解密互通
Rsa 加密标准的制定已经过去了十多年了. 这两天在看rsa 加密的文章,基本上都是在说 .net 与 java 之间的 rsa加密是不能互通的.因为项目有用到,所以花了点时间对rsa加密做了一点点了 ...
- java关于split分割字符串,空的字符串不能得到的问题
java关于split分割字符串,空的字符串不能得到的问题 class T { public static void main(String args[]) { String num[] = ne ...