Ioc容器Autofac系列(1)-- 初窥
一.前言
第一次接触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;
}
// .......
}
上面代码中,ContainerBuilder和IContainer是Autofac中的核心类(之后的文章中会介绍,本文不赘述)。当我们要实例化一个ProductService时,需要写如下代码:
var productService = container.Resolve<ProductService>();
没有任何跟Log有关的操作,但productService中的_log变量确已被赋值了一个Log的实例。Ioc容器会在已注册的组件(类或接口)中匹配实例化参数的类型,一旦发现该类型注册过,则自动将对应的实例赋值给该类型,这个过程叫做--构造函数注入。
回头看看那个曾经折磨过我们的TxtLog换DbLog的问题,托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)-- 初窥的更多相关文章
- Ioc容器Autofac系列(3)-- 三种注册组件的方式
简单来说,所谓注册组件,就是注册类并映射为接口,然后根据接口获取对应类,Autofac将被注册的类称为组件. 虽然可像上篇提到的一次性注册程序集中所有类,但AutoFac使用最多的还是单个注册.这种注 ...
- Ioc容器Autofac系列(2)-- asp.net mvc中整合autofac
经过上篇蜻蜓点水的介绍后,本篇通过实例快速上手autofac,展示当asp.net mvc引入了autofac之后会带来什么. 创建Asp.net MVC并引入Autofac 首先,创建一个MVC站点 ...
- Ioc容器Autofac系列
1.http://blog.csdn.net/xingxing513234072/article/details/9211969 2.asp.net mvc中整合autofachttp://blog. ...
- [转]Ioc容器Autofac
本文转自:http://www.cnblogs.com/hkncd/archive/2012/11/21/2780041.html Ioc容器Autofac系列(1)-- 初窥 前言 第一次接触A ...
- .net core2.0下Ioc容器Autofac使用
.net core发布有一段时间了,最近两个月开始使用.net core2.0开发项目,大大小小遇到了一些问题.准备写个系列介绍一下是如何解决这些问题以及对应技术.先从IOC容器Autofac开始该系 ...
- IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用
Autofac结合EF在MVC中的使用,上一篇IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)已经介绍了.但是只是MVC中Co ...
- IoC容器Autofac - Autofac + Asp.net MVC + EF Code First(转载)
转载地址:http://www.cnblogs.com/JustRun1983/archive/2013/03/28/2981645.html 有修改 Autofac通过Controller默认构造 ...
- IoC容器Autofac学习笔记
一.一个没有使用IoC的例子 IoC的全称是Inversion of Control,中文叫控制反转.要理解控制反转,可以看看非控制反转的一个例子. public class MPGMovieList ...
- IOC容器 - Autofac概述
Autofac是比较出名的Ioc容器之一,熟悉Orchard的应该熟知.本文直接介绍autofac用法 一.开始 1.NuGet添加或者直接http://code.google.com/p/autof ...
随机推荐
- Spark入门实战系列--6.SparkSQL(下)--Spark实战应用
[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .运行环境说明 1.1 硬软件环境 线程,主频2.2G,10G内存 l 虚拟软件:VMwa ...
- WebStorm 9 自动编译 SCSS 产出 CSS 和 source maps
1. 上一节我们学习了Windows下搭建Ruby开发环境,也为这一节的学习做了铺垫.因为本节需要在Ruby环境下安装SASS.详细请见:http://www.cnblogs.com/wind128 ...
- Deep learning:四十四(Pylearn2中的Quick-start例子)
前言: 听说Pylearn2是个蛮适合搞深度学习的库,它建立在Theano之上,支持GPU(估计得以后工作才玩这个,现在木有这个硬件条件)运算,由DL大牛Bengio小组弄出来的,再加上Pylearn ...
- WTF Forms – 使用 CSS 实现用户体验更好的表单
WTF forms 借助 CSS 提供友好的 HTML 表单控件,专为 IE9+ 以及最新的 Chrome.Safari 和 Firefox 浏览器.以文件输入控件的改进,使用 label 包裹在 i ...
- Android的UI设计与后台线程交互
本文将讨论Android应用程序的线程模型以及如何使用线程来处理耗时较长的操作,而不是在主线程中执行,保证用户界面(UI)的流畅运行.本文还将阐述一些用户界面(UI)中与线程交互的API.UI用户界面 ...
- Elasticsearch 之 数据索引
对于提供全文检索的工具来说,索引时一个关键的过程——只有通过索引操作,才能对数据进行分析存储.创建倒排索引,从而让使用者查询到相关的信息. 本篇就ES的数据索引操作相关的内容展开: 更多内容参考:El ...
- Html页面head标签元素的意义和应用场景
相信在html5之前,很少人会关注html页面上head里标签元素的定义和应用场景,可能记得住的只有"title"."keyword"和"descri ...
- C语言学习020:可变参数函数
顾名思义,可变参数函数就是参数数量可变的函数,即函数的参数数量是不确定的,比如方法getnumbertotal()我们即可以传递一个参数,也可以传递5个.6个参数 #include <stdio ...
- C#反射技术概念作用和要点
反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获得.NET中每一个类型(包括类.结构.委托.接口和枚举等)的成员,包括方法.属性.事件,以及构造函数等.还可以获得每个成员的 ...
- sqlserver 中存储过程的基础知识记录
1.什么是存储过程? 存储过程就是作为可执行对象存放在数据库中的一个或多个SQL命令. 通俗来讲:存储过程其实就是能完成一定操作的一组SQL语句. 2.为什么要用存储过程? 1)存储过程只在创建时进行 ...