Autofac 处理生命周期范围
创建新的生命周期范围
你可以通过调用任何现有生命周期范围的 BeginLifetimeScope()
方法来创建一个新范围,从根容器开始。生命周期范围是可丢弃的,并且会跟踪组件的卸载,请确保始终调用 "Dispose()" 或使用 using
语句包裹它们。
using (var scope = container.BeginLifetimeScope())
{
// 从根容器的子范围中解析服务。
var service = scope.Resolve<IService>();
// 你也可以创建嵌套范围...
using (var unitOfWorkScope = scope.BeginLifetimeScope())
{
var anotherService = unitOfWorkScope.Resolve<IOther>();
}
}
标记生命周期范围
有些情况下,你希望在工作单元之间共享服务,但又不想像单例那样全局共享这些服务。一个常见的例子是在 Web 应用程序中的 “每个请求” 生命周期(有关更多信息,请参阅 “实例范围” 主题 )。在这种情况下,你希望标记你的生命周期范围,并将服务注册为 InstancePerMatchingLifetimeScope()
。
例如,假设你有一个发送电子邮件的组件。在系统中,一个逻辑事务可能需要发送多封邮件,因此可以在各个逻辑事务片段之间共享该组件。然而,你不希望电子邮件组件成为全局单例。你的设置可能看起来像这样:
// 将你的事务级别共享组件注册为 InstancePerMatchingLifetimeScope,并为其分配一个“已知标签”,当启动新的事务时,将使用此标签。
var builder = new ContainerBuilder();
builder.RegisterType<EmailSender>()
.As<IEmailSender>()
.InstancePerMatchingLifetimeScope("transaction");
// 订单处理器和收据管理器都需要发送电子邮件通知。
builder.RegisterType<OrderProcessor>()
.As<IOrderProcessor>();
builder.RegisterType<ReceiptManager>()
.As<IReceiptManager>();
var container = builder.Build();
// 使用带有标签的事务范围创建事务。
using (var transactionScope = container.BeginLifetimeScope("transaction"))
{
using (var orderScope = transactionScope.BeginLifetimeScope())
{
// 这将解析一个 IEmailSender 使用,但 IEmailSender 将 “驻留在” 父事务范围中,并因为这个标签而在事务范围的所有子范围之间共享。
var op = orderScope.Resolve<IOrderProcessor>();
op.ProcessOrder();
}
using (var receiptScope = transactionScope.BeginLifetimeScope())
{
// 这也将解析一个 IEmailSender 使用,但它会在父范围中找到现有的 IEmailSender 并使用它。它将是与订单处理器使用的同一实例。
var rm = receiptScope.Resolve<IReceiptManager>();
rm.SendReceipt();
}
}
再次强调,有关更多关于带标签范围和每个请求范围的信息,请参阅 “实例范围” 主题 。
向生命周期范围添加注册项
Autofac 允许你在创建生命周期范围时动态添加注册项。这在你需要进行某种 “临时焊接” 有限注册重写或通常只是需要在范围中添加一些不想全局注册的东西时很有帮助。你通过传递一个接受 ContainerBuilder
的 Lambda 表达式给 BeginLifetimeScope()
来完成这一点。
using (var scope = container.BeginLifetimeScope(
builder =>
{
builder.RegisterType<Override>().As<IService>();
builder.RegisterModule<MyModule>();
}))
{
// 这些额外的注册项将仅在这个生命周期范围内可用。
}