在上篇Autofac基本使用步骤中,我们知道Autofac通过创建一个ContainerBuilder对象来注册组件,这个builder是通过服务来暴露组件,后续我们只需要知道服务即可,得到具体组件实例.
在Autofac中的术语请点击此链接查看==>术语
什么是组件(components)?
分三类:
1. reflection(.NET 类型, 或者泛型)
2.现成的实例.(我们创建的类型的实例)
3.Lambda表达式(执行对象实例化的匿名函数)
Auotfac 为ContainerBuilder提供Register()家族方法设置注册组件,每个组件通过调用 ContainerBuilder的As()方法来暴露一个或者多个服务。
//创建一个用于注册组件/服务的Builder. var builder = new ContainerBuilder();//注册一个类型 builder.RegisterType<ConsoleLogger>.As<ILogger>(); // 注册一个现成的实例var output = new StringWriter(); builder.RegisterInstance(output).As<TextWriter>(); // 注册一个执行创建对象的表达式. builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>(); //构建一个container来完成注册动作,同时保存这个container来以备后面解析对象. var container = builder.Build(); //现在我们可以解析服务,等到我们想要是实例. using(var scope = container.BeginLifetimeScope()) { var reader = container.Resolve<IConfigReader>(); }
- 一.Reflection 组件
有2个注册Reflection的方法,一个是泛型方法,一个普通的方法(传入的参数类型是Type类型).
下面是这个2个注册方法.
var builder = new ContainerBuilder(); builder.RegisterType<ConsoleLogger>(); builder.RegisterType(typeof(ConfigReader));
当使用基于Reflection 组件时,Autofac 会自动使用这个类参数最多的构造函数,这个参数必须能够从Container中解析得到.
例如:
我有这么个类.
public class MyClass { public MyClass() { /* ... */ } public MyClass(ILogger logger) { /* ... */ } public MyClass(ILogger logger, IConfigReader reader) { /* ... */ } }
然后我在Aufo进行组件注册:
var builder = new ContainerBuilder(); builder.RegisterType<MyClass>(); builder.RegisterType<ConsoleLogger>().As<ILogger>(); var container = builder.Build(); using(var scope = container.BeginLifetimeScope()) { var component = container.Resolve<MyComponent>(); }
这个时候,找到参数最多的构造函数是MyClass类的第2个构造函数,而不第3个. 因为我们注册了ILogger服务的组件,而没有注册IConfigReader服务的组件.所以container能解析到构造器的一个参数,因此Aufofac自动选择了第2个构造函数.
我也可以改变Aufofac自动选择构造函数的行为,从而实现手动选择.UsingConstructor方法能够满足我们的要求.
builder.RegisterType<MyClass>() .UsingConstructor(typeof(ILogger), typeof(IConfigReader));
基于Reflection组件总结:
1.任何组件类型都必须通过"RegisterType"方法注册,而且注册的类型必须是一个具体的类型,不能是接口或者抽象类型.虽然我们可以暴露一个接口或抽象类作为服务,但不能把他们作为组件注册.
2.我可以使用UsingConstructor方法改变Autofac自动选择构造器的特性.
二. 实例组件.
我们可以通过"RegisterInstance"方法把已经创建的对象的实例注册到服务上.通过服务,暴露给大家使用.
var output = new StringWriter(); builder.RegisterInstance(output).As<TextWriter>();
三.Lambda表达式组件
Reflection 组件是和很好的选择,但是有些时候,组件的创建逻辑不是简单的构造器调用,而是一个复杂的逻辑,因此Autofac允许用委托或者Lambda表达式作为一个组件的创建者.
builder.Register(c => new A(c.Resolve<B>()));
说明: 在上面代码中,可以看到有一个c参数提供给表达式,这个参数是组件上下文(IComponentContext类型对象),我们可以在表达式中使用它从Container中解析出你创建组件是所需要的实例.