上篇文章中(IoC容器Autofac(1) -- 什么是IoC以及理解为什么要使用Ioc),我们用自己的方式实现了一个简陋的工厂类来实现IoC.

这里我们尝试使用Auotfac来替换我们的工厂类MovieFinderFactory.

(Autofac的名字应当取的是非常贴切的,它本质上其实就是一个产出对象的自动工厂)

阅读目录:

一. 使用自定义工厂类实现IoC的例子

二. 改造代码,去除MovieFinderFactory

三. 应用Autofac替代工厂类

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

五. Autofac对程序架构的影响

六. 总结

一、使用自定义工厂类实现IoC的例子

我们回顾一下之前的代码:

//这个类的作用是筛选出MPG类型的电影
public class MPGMovieLister:IMovieFinder
{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() }

这里MPGMovieLister已经不和具体的MovieFinder耦合了,而是依赖于MovieFinderFactory工厂类提供的IMovieFinder接口的具体实现来取Movie数据。

所以工厂类只要返回不同的实现IMovieFinder的实例,就能够让MovieLister从列表,文本,数据库,web service …… 中获取数据。

二、改造代码,去除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>().AsImplementedInterfaces();//注册ListMovieFinder类型,这里的AsImplementedInterfaces表示以接口的形式注册
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中就可以了。同时做业务逻辑层的单元测试也非常容易了。

拿上面的例子来说,就是这个样子:

var builder = new ContainerBuilder();
if(IsLive)//如果是正式环境中,使用DBMovieFinder, 从数据库中获取数据
{builder.RegisterType<DBMovieFinder>().AsImplementedInterfaces();
}
else//在开发环境中,先用Stub类ListMovieFinder替代
{builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces();
}
builder.RegisterType<MPGMovieLister>();
_container = builder.Build();

同样的,UI层和业务逻辑层也可以运用同样的思路。

六、 总结

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

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

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

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

相关源代码下载: AutofactDemo.zip

相关文章:

IoC容器Autofac(1) -- 什么是IoC以及理解为什么要使用Ioc

IoC容器Autofac(3) - 理解Autofac原理,我实现的部分Autofac功能(附源码)

IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)

理解为什么要使用Ioc

分析Autofac如何实现Controller的Ioc(Inversion of Control)

IoC容器Autofac(2) - 一个简单示例(附demo源码)相关推荐

  1. NLP文本预处理:步骤、示例 | 附github源码

    点击关注我哦 一篇文章带你了解NLP文本预处理:步骤.示例 | 附github源码 注:关注[小白玩转Python]公众号,后台回复[NLP文本预处理],可以获取完整源码以及项目所需数据集. 文本数据 ...

  2. echarts圆柱形柱状图 源码_jQuery插件echarts实现的多柱子柱状图效果示例【附demo源码下载】...

    jQuery插件echarts实现的多柱子柱状图效果示例[附demo源码下载] 发布时间:2020-09-08 07:46:02 来源:脚本之家 阅读:74 作者:翱翔天地 本文实例讲述了jQuery ...

  3. java计算机毕业设计vue开发一个简单音乐播放器源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计vue开发一个简单音乐播放器源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计vue开发一个简单音乐播放器源码+mysql数据库+系统+lw文档+部署 本源码技 ...

  4. 计算机毕业设计Javavue开发一个简单音乐播放器(源码+系统+mysql数据库+lw文档)

    计算机毕业设计Javavue开发一个简单音乐播放器(源码+系统+mysql数据库+lw文档) 计算机毕业设计Javavue开发一个简单音乐播放器(源码+系统+mysql数据库+lw文档) 本源码技术栈 ...

  5. 一个简单的IPmsg程序源码分析(二)

    离上篇一个简单的IPmsg程序源码分析(一)已经基本半个月(上篇最初发布在点点上面,后边纠结了一下还是选择了博客园),利用空闲的时间终于把源码的构架和一些细节基本都搞清楚了,总的来说是很简单的一个客户 ...

  6. 微信小程序开发之文件上传下载应用场景(附Demo源码)

    微信小程序开发之文件上传下载应用场景(附Demo源码),Demo为小相册应用,源码在附件中,本示例需要腾讯云支持. http://www.henkuai.com/forum.php?mod=viewt ...

  7. 最新小程序授权+php后端(附demo源码)

    参考博客:小程序授权+php后端(附demo源码)_流情的博客-CSDN博客_php小程序 正所谓计划永远赶不上变化,鉴于小程序端已经更改了微信授权登录的接口,因此特来补充一下.原先的wx.getUs ...

  8. winserver的consul部署实践与.net core客户端使用(附demo源码)

    前言 随着微服务兴起,服务的管理显得极其重要.都知道微服务就是"拆",把臃肿的单块应用,拆分成多个轻量级的服务,每个服务可以在短周期内重构.迭代.交付.随着微服务的数量增多,因量变 ...

  9. 分享基于白鹭Egret联合Matchvs开发的足球游戏(附Demo源码)

    Demo简介 本游戏使用Matchvs的实时联网SDK和白鹭Egret开发,并提供了简洁的Demo来展示多人实时联网游戏的开发过程和效果,用于演示多人匹配.数据传输.帧同步.创建房间.获取房间列表.消 ...

最新文章

  1. 拆包--缓冲区查找包头及包尾偏移
  2. struts2整合spring应用实例
  3. ajax get 缓存 ie,Ajax异步同步请求被IE缓存的问题解决方法(get方式)
  4. 计算机软件著作权申请教程攻略,提供 软件使用说明和源代码文档,全套模板
  5. 2017年十大移动应用开发的测试工具
  6. Hamcrest使用
  7. jrtplib使用笔记
  8. k3c最新官改非常稳定了_2020国庆过后玉米价格最新行情走势
  9. Tess4J 安装及使用介绍
  10. matlab中 点到线的距离,点到空间直线的距离 | 学步园
  11. 第三方验收测试报告怎么做?
  12. [小工具] LenovoOneLite 多屏协同工具
  13. 库存盘点后的盘点差异解决方法
  14. 80后 最牛的辞职信
  15. Windows启动配置数据(BCD)存储文件包含一些无效信息
  16. python for ArcGIS 绘制上海市环线地图
  17. Chrome 53 Beta一些有意思的改动
  18. sql 累计占比_SQL语句-求总和的百分比
  19. 编译jrtplib和jthread
  20. 以太网、局域网、广域网、因特网、互联网与万维网

热门文章

  1. ANDROID调用webservice带soapheader验证
  2. 路由总结之静态、RIP、OSPF、IS-IS、BGP和策略路由
  3. (Mark)JS中的上下文
  4. WPF4.5 Cockbook - Chapter8(Style, Triggers and Control Template)
  5. Oracle 查看 表 存储过程 触发器 函数 等对象定义语句的方法
  6. 监控ajax上传进度
  7. 新代系统cnc怎样连接电脑_你真的了解3C产线上的运控系统吗?
  8. CSS盒子的三种类型(border-box、content-box)
  9. 3层b+树索引访问磁盘次数_从B+树到LSM树,及LSM树在HBase中的应用
  10. jQuery左右循环滚动图片特效