创建一个新的生命周期范围
您可以通过在任何现有生命周期作用域上从根容器开始调用BeginLifetimeScope()
方法来创建生命周期作用域。生命周期作用域是可销毁的,他们跟踪组件的处置,所以确保你总是调用“Dispose()”
或者把它们包装在“using”
语句中。
using(var scope = container.BeginLifetimeScope())
{
//从作为根容器子项的作用域来解析服务
var service = scope.Resolve<IService>();
//您也可以创建嵌套的作用域...
using(var unitOfWorkScope = scope.BeginLifetimeScope())
{
var anotherService = unitOfWorkScope.Resolve<IOther>();
}
}
标记生命周期范围
在某些情况下,您希望跨工作单元共享服务,但您不希望像单例模式那样在全局共享这些服务。 Web应用程序中的一个常见示例是“per-request”生命周期。(您可以在“实例范围”主题中阅读有关per-request范围的更多信息。)在这种情况下,您需要标记生命周期范围并将服务注册为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();
}
}
同样,您可以在“实例范围”主题中阅读有关标记范围和per-request 范围的更多信息。
添加注册到生命周期范围
Autofac允许您在创建生命周期范围时“随时”添加注册。 当您需要进行某种“点焊”有限的注册覆盖时,或者您通常只需要一些您不希望在全局范围内注册的附加东西时,这可以帮助您。 通过将一个lambda传递给使用ContainerBuilder
并添加注册的BeginLifetimeScope()
来完成此操作。
using(var scope = container.BeginLifetimeScope(
builder =>
{
builder.RegisterType<Override>().As<IService>();
builder.RegisterModule<MyModule>();
}))
{
// 额外的注册将只在这个生命周期范围内可用。
}