回顾以前的代码数据库
//这个类的做用是筛选出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() }
在应用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改造上面的代码。单元测试
第一步: 从Nuget中添加Autofac引用测试
第二步:ui
* 建立一个ContainerBuilder对象(ContainerBuilder从字面的意思就是用来建立Container(容器)的,而Conainter就是咱们从中取各类咱们须要对象的地方)spa
* 注册咱们后面将从容器中取出对象的类型。调试
代码是这样:code
var builder = new ContainerBuilder(); builder.RegisterType<ListMovieFinder>().As<IMovieFinder>();//注册ListMovieFinder类型 builder.RegisterType<MPGMovieLister>();//注册MPGMovieLister类型
* 建立容器xml
_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();
上面的例子中类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();
常见的程序架构大概是: UI层, 业务逻辑层, 持久层(数据层)。
咱们可用Autofac做为不一样层之间的中间人,让UI层依赖于业务逻辑层的抽象接口,业务逻辑层依赖于持久层的接口,而实际运行过程当中的实例都由Auotfac来提供。
这样就可以解除不一样层之间的依赖,将全部的注册类型的操做在一个核心函数或者核心类中实现,那么只要修改这个函数或者类就可以很是方便的让它们之间的依赖关系发生变化。
好比 在一个大的项目中,持久层和业务逻辑层是并行开发的,并且是不一样团队开发,这个时候业务逻辑开发团队的人在没有持久层代码的状况下,如何开始呢?
咱们只要定义好持久层的接口, 业务逻辑团队再写一些Stub类(桩类)来实现这些接口,让这些Stub类来替换真正的持久层,所要作的就只是简单的把这些Stub类型注册到Autofac中就能够了。同时作业务逻辑层的单元测试也很是容易了。
从上面的例子能够看出,使用IoC对于复杂的项目来讲,很是有意义,可以为咱们搭建一个好的开发层次。
同时,在使用过程当中,还可以发现Autofac有如下优势:
1. 可使用C#代码来完成注册配置,很是方便并且便于调试。(使用xml配置,每每容易出现格式不对,或者其它问题,很是难于调试和排错)
2. 很是聪明,可以自动装配(发现构造函数须要的必须参数的时候,会本身想办法解决)