当需要灵活且功能强大的DI组件时,考虑使用autofac。
```c
var builder = new ContainerBuilder();
builder.RegisterType<TestService>().As<ITestService>();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var service = container.Resolve<ITestService>();
var result = service.GetList();
}
```
## 一、注册
- 注册的为组件,暴露的为服务
- 每个组件暴露一个或多个服务,使用 As()方法连接起来
- 注册组件只能解析组件,不能使用服务去解析。注册组件且暴露服务后,服务将覆盖组件的解析。
例如:
```c
builder.RegisterType<CallLogger>();
scope.Resolve<CallLogger>();
scope.Resolve<ILogger>();//错误不能解析
```
- 默认情况下暴露多个服务后,由最后一个服务覆盖。可使用.AsSelf()使得一起可用。
- 暴露的相同的服务,则由最后一个覆盖。可通过PreserveExistingDefaults指定默认服务提供。
### 1.1 接口注册
```c
builder.RegisterType<ConsoleLogger>().As<ILogger>();
```
### 1.2 实例注册(已有对象)
```c
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();
builder.RegisterInstance(output).As<TextWriter>().ExternallyOwned();//需考虑释放,若需自己控制生命周期则
```
### 1.3 Lambda注册(灵活)
```c
builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>();
//判断注入:
builder.Register<CreditCard>((c, p) =>
{
var accountId = p.Named<string>("accountId");
if (accountId.StartsWith("9"))
{
return new GoldCard(accountId);
}
return new StandardCard(accountId);
});
//第二个参数可选
var card = container.Resolve<CreditCard>(new NamedParameter("accountId", "12345"));
```
### 1.4 反射注册
默认自动匹配最多参数的构造方法,必须是实体类。解析时仍然需要提供必要的参数。
```c
builder.RegisterType<ConsoleLogger>();
builder.RegisterType(typeof(ConfigReader));
```
指定构造函数:
```c
builder.RegisterType<MyComponent>().UsingConstructor(typeof(ILogger), typeof(IConfigReader));
```
### 1.5 开放泛型注册
容器请求一个匹配的服务类型时, Autofac会找到对应的封闭类型的具体实现
```c
builder.RegisterGeneric(typeof(NHibernateRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
```
### 1.6 条件注册
```c
//IfNotRegistered 未注册IService则注册
builder.RegisterType<ServiceB>().As<IService>().IfNotRegistered(typeof(IService));
//OnlyIf 只有注册了IServer才注册IManager
builder.RegisterType<Manager>().As<IManager>().OnlyIf(reg => reg.IsRegistered(new TypedService(typeof(IService))));
```
## 二、注册时传参(解析式传参也可以)
### 2.1 NamedParameter - 通过名字匹配目标参数(常量)
```c
builder.RegisterType<ConfigReader>().As<IConfigReader>().WithParameter("configSectionName", "sectionName");
```
### 2.2 TypedParameter - 通过类型匹配目标参数 (需要匹配具体的类型)
```c
builder.RegisterType<ConfigReader>().As<IConfigReader>().WithPara