Autofac是一个轻量级的依赖注入的框架,同类型的框架还有Spring.NET,Unity,Castle等。
Autofac的使用有一个非常让人郁闷的地方,就是服务器要求安装有Microsoft .NET Framework 4 KB2468871。该补丁的地址是:http://www.microsoft.com/zh-cn/download/confirmation.aspx?id=3556 如果不安装,则运行程序会报如下错误:
具体信息可以到这里去查看:https://code.google.com/p/autofac/wiki/FrequentlyAskedQuestions
namespace ConsoleApplication3 { class Program { static void Main(string[] args) { ContainerBuilder builder = new ContainerBuilder();//类型通过此对象注册到容器中 builder.RegisterType<AutoFacManager>();//注册类型 builder.RegisterType<Worker>().As<IPerson>();//注册类型且用as方法指定此类型是IPerson接口 using (IContainer container = builder.Build())//build方法创建容器 { AutoFacManager manager = container.Resolve<AutoFacManager>();//通过resolve方法取得对象 manager.Say(); } Console.ReadKey(); } } public interface IPerson { void Say(); } public class Worker : IPerson { public void Say() { Console.WriteLine("我是一个工人!"); } } public class Student : IPerson { public void Say() { Console.WriteLine("我是一个学生!"); } } public class AutoFacManager { IPerson person; public AutoFacManager(IPerson MyPerson) { person = MyPerson; } public void Say() { person.Say(); } } }
以上例子,是一个最简单的例子,输出如下:
所谓注册组件,就是注册类并映射为接口,然后根据接口获取对应类,Autofac将被注册的类称为组件(类只是其中一种)。有如下方式
1、类型创建RegisterType
AutoFac能够通过反射检查一个类型,选择一个合适的构造函数,创造这个对象的实例。主要通过RegisterType<T>() 和 RegisterType(Type) 两个方法。
builder.RegisterType<AutoFacManager>(); builder.RegisterType<Worker>().As<IPerson>();
2、实例创建
builder.RegisterInstance<AutoFacManager>(new AutoFacManager(new Worker()));
单例
builder.RegisterInstance(MySingleton.GetInstance()).ExternallyOwned(); //将自己系统中原有的单例注册为容器托管的单例
这种方法会确保系统中的单例实例最终转化为由容器托管的单例实例。
3、默认的注册
如果一个类型被多次注册,以最后注册的为准。通过使用PreserveExistingDefaults() 修饰符,可以指定某个注册为非默认值。
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<AutoFacManager>(); builder.RegisterType<Worker>().As<IPerson>(); builder.RegisterType<Student>().As<IPerson>().PreserveExistingDefaults(); //指定Student为非默认值 using (IContainer container = builder.Build()) { AutoFacManager manager = container.Resolve<AutoFacManager>(); manager.Say(); //输出我是一个工人 如果不使用PreserveExistingDefaults(),那么将输出“我是一个学生”。 }
如何区分组件(或者叫服务)?
简单的As方法(同1)将组件指定为某一类型接口
例如ArrayList继承了IEnumerable接口,若将其注册到Autofac中,写法如下所示: ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<ArrayList>().As<IEnumerable>(); IContainer container = builder.Build(); ArrayList result = (ArrayList)container.Resolve<IEnumerable>();
第二种方式--Named方法
有时难免碰到多个类映射到同一种接口,比如ArrayList和SortedList都继承了IEnumerable接口,
为了准确获取想要的类型,就有了第二种方式--Named方法,可根据字符串注册并解析相应的类。代码如下: builder.RegisterType<ArrayList>().Named<IEnumerable>("array"); builder.RegisterType<SortedList>().Named<IEnumerable>("sort"); // then IContainer container = builder.Build(); ArrayList result = (ArrayList)container.ResolveNamed<IEnumerable>("array"); SortedList result1 = (SortedList)container.ResolveNamed<IEnumerable>("sort");
相对于字符串,枚举更易读易用 但在Autofac中使用枚举会有些麻烦,因为Named只接受字符串,必须将枚举转换成字符串才能使用。
比如,现在用ListType枚举来代替“array”和“sort”字符串。如下所示:
public enum ListType{ Array, Sort }
builder.RegisterType<ArrayList>().Named<IEnumerable>(ListType.Array.ToString());
这种转换略显笨拙且让枚举失去原有价值。于是为不多此一举,
第三种方式就产生了--Keyed方式,
该方法可以接受任何类型作为参数。以上文中的ListType枚举为例,代码如下: builder.RegisterType<ArrayList>().Keyed<IEnumerable>(ListType.Array); builder.RegisterType<SortedList>().Keyed<IEnumerable>(ListType.Sort); // then IContainer container = builder.Build(); ArrayList result = (ArrayList)container.ResolveKeyed<IEnumerable>(ListType.Array); SortedList result1 = (SortedList)container.ResolveKeyed<IEnumerable>(ListType.Sort); 但从功能上来讲,Autofac的设计者推荐第三种。
通过IIndex索引查找被Keyed标识过的类
如果使用Keyed方法注册类,可通过Autofac内置索引来查找指定的值,索引的类型是IIndex<Tkey,TValue>,
以上文的枚举为例,可通过索引完成解析,代码如下:
IIndex<ListType, IEnumerable> allList = container.Resolve<IIndex<ListType, IEnumerable>>();
ArrayList result = (ArrayList)allList[ListType.Array];
SortedList result1 = (SortedList)allList[ListType.Sort];
IIndex中第一个泛型参数要跟注册时一致,这里是ListType枚举。其他两种注册方法没有这样的索引查找功能,这也是为什么设计者推荐Keyed注册的原因之一。
更多内容参考 : http://www.cnblogs.com/kissdodog/p/3611799.html