服务范围:
实例范围决定了在同一服务的请求之间如何共享实例。服务的范围是应用程序中可以与使用该服务的其他组件共享该服务的区域。例如,在您的应用程序中,您可能具有全局静态单例-该全局对象实例的“范围”将是整个应用程序。
服务生命周期:
服务的生命周期是服务实例在程序中生存的时间。例如您“新建”一个实现IDisposable的对象,然后再对其进行调用Dispose()。
Lifetime Scope(生命周期范围):
Autofac中生命周期范围的概念结合了这两个概念。实际上,生命周期范围等同于应用程序中的一个工作单元。一个工作单元可以在开始时开始一个生命周期范围,然后该工作单元所需的服务将从一个生命周期范围得到解析。当您解析服务时,Autofac跟踪已解析的一次性(可配置)组件。在工作单元结束时,您将释放相关的生命周期范围,Autofac将自动清理/释放解析后的服务。
务必始终从生命周期范围而不是根容器来解析服务。由于生命周期作用域的处置跟踪特性,如果您从容器(“根生命周期作用域”)中解析许多可丢弃组件,您可能会无意中给自己造成内存泄漏。根容器将一直保存对这些可丢弃组件的引用,直到其存在(通常是应用程序的生存期),因此它可以释放这些组件。
手动创建作用域:
您可以通过BeginLifetimeScope()从根容器开始在任何现有生存期范围上调用方法来创建生存期范围。生命周期范围是一次性的,并且它们跟踪组件的处置,因此请确保始终调用“ Dispose()”或将它们包装在“ using”语句中。
using(var scope = container.BeginLifetimeScope())
{
//从容器的一个子作用域解析服务
var service = scope.Resolve();
// 还可以创建嵌套的作用域
using(var unitOfWorkScope = scope.BeginLifetimeScope())
{
var anotherService = unitOfWorkScope.Resolve();
}
}
生命周期有以下几种:
瞬时(Per Dependency):每次请求都会创建新实例
builder.RegisterType<Worker>().InstancePerDependency();
单例(Single Instance):所有对父容器或嵌套容器的请求都返回一个实例
builder.RegisterType<Worker>().SingleInstance();
Per Lifetime Scope:
这个作用域适用于嵌套的生命周期。一个使用Per Lifetime 作用域的component在一个 nested lifetime scope内最多有一个实例。
当对象特定于一个工作单元时,这个非常有用。比如,一个HTTP请求,每一个工作单元都会创建一个nested lifetime,如果在每一次HTTP请求中创建一个nested lifetime,那么其他使用 per-lifetime 的component在每次HTTP请求中只会拥有一个实例。
builder.RegisterType<Worker>().InstancePerLifetimeScope();
上下文
有时候你可能需要在Unit of work内共享一些服务,但是又不希望采用全局的共享便利,如单例模式。例如web应用的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将“驻留”在父事务作用域中,并且在作用域中的任何子作用域中共享
var op = orderScope.Resolve<IOrderProcessor>();
op.ProcessOrder();
}
using(var receiptScope = transactionScope.BeginLifetimeScope())
{
var rm = receiptScope.Resolve<IReceiptManager>();
rm.SendReceipt();
}
}
参考:
https://autofaccn.readthedocs.io/en/latest/lifetime/working-with-scopes.html