Autofac官方文档(十一)【使用生命周期范围】

时间:2020-12-24 14:42:12

创建一个新的生命周期范围

您可以通过在任何现有生命周期作用域上从根容器开始调用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>();
  }))
{
  // 额外的注册将只在这个生命周期范围内可用。
}