回顾之前的代码

//这个类的作用是筛选出MPG类型的电影
public class MPGMovieLister
{
public Movie[] GetMPG()
{
var finder = MovieFinderFactory.GetFinder();//这里调用工厂类获取具体的实例,得到一个电影列表
var allMovies = finder.FindAll();
return allMovies.Where(m => m.Name.EndsWith(".MPG")).ToArray();
}
} public class MovieFinderFactory
{
public static IMovieFinder GetFinder()
{
return new ListMovieFinder();
}
} public class ListMovieFinder :IMovieFinder
{
public List<Movie> FindAll()
{
return new List<Movie>
{
new Movie
{
Name = "Die Hard.wmv"
},
new Movie
{
Name = "My Name is John.MPG"
}
};
}
} public interface IMovieFinder { List<Movie> FindAll() }

二、改造代码,去除MovieFinderFactory

在应用Autofac替换MovieFinderFactory之前,我们先从代码中去掉MovieFinderFactory, 改动之后的代码是这样:

public class MPGMovieLister
{
private readonly IMovieFinder _movieFinder;
//增加了构造函数,参数是IMovieFinder对象
public MPGMovieLister(IMovieFinder movieFinder)
{
_movieFinder = movieFinder;
} public Movie[] GetMPG()
{
var allMovies = _movieFinder.FindAll();
return allMovies.Where(m => m.Name.EndsWith(".MPG")).ToArray();
}
} public interface IMovieFinder
{
List<Movie> FindAll()
}

  我们去掉了工厂类MovieFinderFactory, 改造了MPGMovieLister, 添加了一个构造函数, 构造函数要求使用MPGMovieLister时,需要提供一个IMovieFinder的实例。

三、应用Autofac替代工厂类

应用Autofac改造上面的代码。

第一步: 从Nuget中添加Autofac引用

第二步:

* 创建一个ContainerBuilder对象(ContainerBuilder从字面的意思就是用来创建Container(容器)的,而Conainter就是我们从中取各种我们需要对象的地方)

* 注册我们后面将从容器中取出对象的类型。

代码是这样:

var builder = new ContainerBuilder();
builder.RegisterType<ListMovieFinder>().As<IMovieFinder>();//注册ListMovieFinder类型
builder.RegisterType<MPGMovieLister>();//注册MPGMovieLister类型

* 创建容器

_container = builder.Build();

第三步: 在程序中使用 _container容器:

var lister = _container.Resolve<MPGMovieLister>();
foreach (var movie in lister.GetMPG())
{
Console.WriteLine(movie.Name);
}

理解一下Autofac为我们在背后做了什么:

首先我们注册了类型ListMovieFinder和MPGMovieLister,这样容器就能够知道如何创建这两种类型的实例了。(类其实是创建对象的模板,当我们把模板注册给Autofac, 它就会遵循这个模板为我们提供实例)

后面的代码中,我们调用Resolve方法,取出一个MPGMovieLister的实例。

_container.Resolve<MPGMovieLister>();

这里还有一个需要解释的,对于MPGMovieLister类型,我们为Autofac提供了类型, 但是当Autofac创建MPGMovieLister的实例, 调用它的构造函数的时候,却遇到了问题:

它的构造函数需要提供一个IMovieFinder的实例作为参数, 聪明的Autofac要在自己的容器里找找,看看没有有办法提供一个IMovieFinder的实例。

这个时候Autofac会发现我们注册过ListMovieFinder且通过AsImplementedInterfaces()方法,指明了就是为接口IMovieFinder提供实例的。

所以Autofac会创建一个ListMovieFinder的实例,作为创建MPGMovieLister时,提供给构造函数的参数。

builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces();

四、当需求发生变动Autofac如何应对?

上面的例子中类ListMovieFinder实现了IMovieFinder接口, 实际运行中由它来提供数据。

假如这个时候,我们要从数据库中获取数据,怎么办?

非常简单,创建一个类DBMovieFinder继承IMovieFinder接口, 然后注册给Autofac就可以了。

var builder = new ContainerBuilder();
builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces();
//这里注册了DBMovieFinder, 这个类继承IMovieFinder接口。因为它也使用了AsImplementedInterfaces,它会覆盖ListMovieFinder的注册。
builder.RegisterType<DBMovieFinder>().AsImplementedInterfaces();
builder.RegisterType<MPGMovieLister>();
_container = builder.Build();

五、Autofac对程序架构的影响

常见的程序架构大概是: UI层, 业务逻辑层, 持久层(数据层)。

我们可用Autofac作为不同层之间的中间人,让UI层依赖于业务逻辑层的抽象接口,业务逻辑层依赖于持久层的接口,而实际运行过程中的实例都由Auotfac来提供。

这样就能够解除不同层之间的依赖,将所有的注册类型的操作在一个核心函数或者核心类中实现,那么只要修改这个函数或者类就能够非常方便的让它们之间的依赖关系发生变化。

比如 在一个大的项目中,持久层和业务逻辑层是并行开发的,而且是不同团队开发,这个时候业务逻辑开发团队的人在没有持久层代码的情况下,如何开始呢?

我们只要定义好持久层的接口, 业务逻辑团队再写一些Stub类(桩类)来实现这些接口,让这些Stub类来替换真正的持久层,所要做的就只是简单的把这些Stub类型注册到Autofac中就可以了。同时做业务逻辑层的单元测试也非常容易了。

六、 总结

从上面的例子可以看出,使用IoC对于复杂的项目来说,非常有意义,能够为我们搭建一个好的开发层次。

同时,在使用过程中,还能够发现Autofac有以下优点:

1. 可以使用C#代码来完成注册配置,非常方便而且便于调试。(使用xml配置,往往容易出现格式不对,或者其它问题,非常难于调试和排错)

2. 非常聪明,能够自动装配(发现构造函数需要的必须参数的时候,会自己想办法解决)

IoC容器Autofac之实例优化(三)的更多相关文章

  1. IoC容器Autofac之实例引入(一)

    先不必尝试理解IOC,先来看段代码. 一.一个没有使用IoC的例子 public class MPGMovieLister { public Movie[] GetMPG() { var finder ...

  2. Ioc容器Autofac系列(1)-- 初窥

     一.前言 第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器.那么,Io ...

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

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

  4. IoC容器Autofac学习笔记

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

  5. [转]Ioc容器Autofac

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

  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. .net core2.0下Ioc容器Autofac使用

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

  8. IOC容器 - Autofac概述

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

  9. ASP.NET中IOC容器Autofac(依赖注入DI 控制反转IOC)

    IOC的一个重点是在程序运行中,动态的向某个对象提供它所需要的其他对象.这一点是通过DI来实现的.Autofac则是比较流行的一款IOC容器. IoC和DI有什么关系呢?其实它们是同一个概念的不同角度 ...

随机推荐

  1. IE6 浏览器常见兼容问题 大汇总(23个)

    IE6以及各个浏览器常见兼容问题 大汇总 综述:虽然说IE6在2014年4月将被停止支持,但是不得不说的是,IE6的市场并不会随着支持的停止而立刻消散下去,对于WEB前端开发工程师来说,兼容IE6 兼 ...

  2. oracle 数据库 分割字符串返回结果集函数

    CREATE OR REPLACE FUNCTION "UFN_SPLIT" (      p_list varchar2,      p_sep varchar2 := ',' ...

  3. C#在foreach循环中修改字典等集合出错的处理

    C#在foreach循环中修改字典等集合出错:System.InvalidOperationException: Collection was modified; enumeration operat ...

  4. (转) How to install eclipse in ubuntu 12.04

    源地址:http://www.krizna.com/ubuntu/install-eclipse-in-ubuntu-12-04/ Eclipse installation in ubuntu 12. ...

  5. IE CSS Bug 系列

    1.[IE CSS Bug系列]IE6&IE7图片链接无效 <!doctype html> <html> <head> <meta charset=& ...

  6. ASP转PHP手记

    打算将动易网站管理系统移植到PHP环境中,寻寻觅觅了很多PHP内容管理网站,发现网上有动易转PHPCMS的代码,所以就拿定注意用PHPCMS的在google上找到一转换程序,动手做来还成功了,现将此次 ...

  7. Jasper_sheetName_defined by parameter or hard coding or filed name

    1.根据传递的参数定义sheet name (jasper sheet name defined by parameter) (1) 获取后台参数 <parameter name="P ...

  8. sqlserver中临时表、row-number、update更新自己

    SELECT * INTO #TempStudent FROM (SELECT id, ROW_NUMBER() OVER(ORDER BY id) RowNum FROM dbo.student) ...

  9. Google Chrome源码剖析【序】

    [序(本人什么都没做,完全转载)] 开源是口好东西,它让这个充斥着大量工业垃圾代码和教材玩具代码的行业,多了一些艺术气息和美的潜质.它使得每个人,无论你来自米国纽约还是中国铁岭,都有机会站在巨人的肩膀 ...

  10. javascript-ajax学习

    /**  *     @todo 封装Ajax 传输类  *     @param params:参数  *    @example 用法: var mAjaxer = new Ajaxer(para ...