一.前言

第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器。那么,Ioc容器是用来做什么的?用了有什么好处?我相信如果不明白这两点就很难敞开心扉接受Ioc容器。

二.传统解耦设计的弊端

为方便描述,举个日志的栗子。我简化实现,一个Log类,一个SaveLog方法。如果其他类想拥有记日志功能,那么只需在内部包含一个Log类型的变量:

   public class Log
{
public void SaveLog(string message) {
// save log here.
}
} public class ProductService {
private Log _log;
public ProductService() {
_log = newLog();
} public void SaveProduct() {
// save product here.
//...
_log.SaveLog("save 1 product");
}
}

有经验的程序员可能会告诉你,这样做会导致其他类与Log耦合。于是,为了解耦,我们将Log类的功能抽象出来,ILog接口就产生了。如此一来,当其他类需要日志功能时,内含变量就从Log变成了ILog

 public interface ILog {
void SaveLog(string message);
}
public class Log:ILog
{
public void SaveLog(string message)
{
// save log here.
}
} public class ProductService
{
private ILog _log;
public ProductService()
{
_log = newLog();
}
// .......
}

由于ILog被抽象出来,它的实现类可多样化,保存为txt、xml、数据库,甚至可扩展出邮件通知功能等。基本上,我看到的国内项目里,所谓的解耦就只能走到这一步了,但这种设计真的是所谓的“灵活,易扩展,高内聚,低耦合”吗?

现在,我们来模拟需求变更。假设已有TxtLog类把日志保存成txt文件,但使用一段时间后发现:这种日志难以查询。项目经理决定将日志保存到数据库,DbLog类应运而生。但是由于整个系统充斥着new TxtLog(),转换过程实质上就是逐个查找TxtLog替换成DbLog的过程。此时,项目大小决定出错率,出错导致日志记录不全,记录不全导致系统故障后查不到日志,查不到日志导致找不到原因,找不到原因导致加班,后果太严重了。

忽然有天,高潮降临,经理或老板决定换回txt或换另外一种日志形式,原因不明,或节省成本,或体验不好,或佞臣谗言,或成心玩你,或与数据库有世仇,总之--TMD就是要换。于是,悲剧的查找替换再次上演,几番折腾,千疮百孔。

而此时此刻,你还会称赞这种设计“灵活,易扩展”吗?

三.迈进IoC大门--改变实例化的方式

现在我们使用Ioc容器--Autofac改进上面的代码,目标是消除代码中的new语句,把实例化类的控制权转移到别的地方,这个地方通常会在一个程序加载时只执行一次的全局方法中。

 public class Global {
public static IContainer container;
public void Application_Start() {
ContainerBuilder builder=newContainerBuilder();
builder.RegisterType<Log>().As<ILog>();
builder.RegisterType<ProductService>();
container = builder.Build();
var productService = container.Resolve<ProductService>();
}
} public class ProductService
{
private ILog _log;
public ProductService(ILog log)
{
_log = log;
}
// .......
}

上面代码中,ContainerBuilderIContainer是Autofac中的核心类(之后的文章中会介绍,本文不赘述)。当我们要实例化一个ProductService时,需要写如下代码:

 var productService = container.Resolve<ProductService>();

没有任何跟Log有关的操作,但productService中的_log变量确已被赋值了一个Log的实例。Ioc容器会在已注册的组件(类或接口)中匹配实例化参数的类型,一旦发现该类型注册过,则自动将对应的实例赋值给该类型,这个过程叫做--构造函数注入。

回头看看那个曾经折磨过我们的TxtLogDbLog的问题,托Ioc的福,只要在那个全局方法中改一下类型就解决了。

四.Ioc不仅仅是控制翻转

也许你会说这个栗子有些极端,实际开发中查找替换的地方并不多,而Ioc只是给实例化换了个地方而已,为了这么一点收益却要付出巨大的学习成本,是否值得?

实际上,Ioc除了控制反转外,还提供了很多对实例生命周期的控制,本文使用的Autofac针对流行的框架(如MVC,WCF)提供了简易整合模块,以及动态代理功能。在不修改原代码的前提下,如何为类中方法添加逻辑?Orchard框架通过Autofac和DynamicProxy库设计出一种很有意思的架构让两个不相干的类的方法逻辑能合并在一起。更多细节,我会在之后的系列文章中向大家展示。

五.结语

5月,天降陨星,三斤大菠萝来袭,我与基友拔剑而起向邪恶宣战。如今战罢收心,准备踏实写一些文章与大家分享,希望这次能坚持久一些^_^。

******************************************************************************

转载:http://www.cnblogs.com/hkncd/archive/2012/11/21/2780041.html

Ioc容器Autofac系列(1)-- 初窥的更多相关文章

  1. Ioc容器Autofac系列(3)-- 三种注册组件的方式

    简单来说,所谓注册组件,就是注册类并映射为接口,然后根据接口获取对应类,Autofac将被注册的类称为组件. 虽然可像上篇提到的一次性注册程序集中所有类,但AutoFac使用最多的还是单个注册.这种注 ...

  2. Ioc容器Autofac系列(2)-- asp.net mvc中整合autofac

    经过上篇蜻蜓点水的介绍后,本篇通过实例快速上手autofac,展示当asp.net mvc引入了autofac之后会带来什么. 创建Asp.net MVC并引入Autofac 首先,创建一个MVC站点 ...

  3. Ioc容器Autofac系列

    1.http://blog.csdn.net/xingxing513234072/article/details/9211969 2.asp.net mvc中整合autofachttp://blog. ...

  4. [转]Ioc容器Autofac

    本文转自:http://www.cnblogs.com/hkncd/archive/2012/11/21/2780041.html Ioc容器Autofac系列(1)-- 初窥   前言 第一次接触A ...

  5. .net core2.0下Ioc容器Autofac使用

    .net core发布有一段时间了,最近两个月开始使用.net core2.0开发项目,大大小小遇到了一些问题.准备写个系列介绍一下是如何解决这些问题以及对应技术.先从IOC容器Autofac开始该系 ...

  6. IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用

    Autofac结合EF在MVC中的使用,上一篇IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)已经介绍了.但是只是MVC中Co ...

  7. IoC容器Autofac - Autofac + Asp.net MVC + EF Code First(转载)

    转载地址:http://www.cnblogs.com/JustRun1983/archive/2013/03/28/2981645.html  有修改 Autofac通过Controller默认构造 ...

  8. IoC容器Autofac学习笔记

    一.一个没有使用IoC的例子 IoC的全称是Inversion of Control,中文叫控制反转.要理解控制反转,可以看看非控制反转的一个例子. public class MPGMovieList ...

  9. IOC容器 - Autofac概述

    Autofac是比较出名的Ioc容器之一,熟悉Orchard的应该熟知.本文直接介绍autofac用法 一.开始 1.NuGet添加或者直接http://code.google.com/p/autof ...

随机推荐

  1. SQLServer学习笔记系列3

    一.写在前面的话 今天又是双休啦!生活依然再继续,当你停下来的时候,或许会突然显得不自在.有时候,看到一种东西,你会发现原来在这个社会上,优秀的人很多,默默 吃苦努力奋斗的人也多!星期五早上按时上班, ...

  2. asp.net App_Code文件夹相关操作

    最近用到了App_Code文件夹,想要实现动态编译文件的方式,即替换文件夹中的类文件从而达到实时修改代码的效果,类似web.config,网上查到的资料基本都是把文件夹中的类文件修改属性为" ...

  3. C#实现WinForm窗体逐渐显示效果

    C#实现WinForm窗体逐渐显示效果,这个博客园里面已经有其它人已经实现了,原理很简单,就是通过定时改变窗体的透明度(从0到1,即透明度从完全透明到不透明),我这里也是按照这个思路来实现的,但是我做 ...

  4. ClojureScript魔法堂:搭建开发环境

    一.前言 当看到Lisp等函数式编程语言的语法是 (say (concat "hello" "world")) 这样的时候,我就有种深入学习的冲动,因为它的语法 ...

  5. 理解SQL Server是如何执行查询的 (2/3)

    查询执行的内存授予(Query Execution Memory Grant) 有些操作符需要较多的内存才能完成操作.例如,SORT.HASH.HAS聚合等.执行计划通过操作符需要处理数据量的预估值( ...

  6. HTML标签理解

    基础回顾 1:<!DOCTYPE HTML> 这个我们都不陌生,它是文档说明,在html页面的第一行就写的是这个.在 html5中只有一个,大小写不敏感.是便于浏览器识别文档类型. 2:& ...

  7. iOS阶段学习第四天笔记(循环)

    iOS学习(C语言)知识点整理笔记 一.分支结构 1.分支结构分为单分支 即:if( ){ } ;多分支 即:if( ){ }else{ }  两种 2.单分支 if表达式成立则执行{ }里的语句:双 ...

  8. C#写爬虫,版本V1.0

    之前看了Sql Server中的基本数据类型,发现image这个类型还是比较特殊的. 于是乎就做了一个将图片以二进制流形式存储的程序http://www.cnblogs.com/JsonZhangAA ...

  9. thinkphp中assign()和display()区别和用法

  10. 修正 XE6 TListView 上方 SearchBok 右边的清除钮显示

    注意:XE7 已修正这个问题. Delphi Firemonkey TListView 提供了搜寻的功能,但在 XE6 以前的版本,可以显示右边的清除按钮,在 XE6 确消失了,这里提供一个修正的方案 ...