TL;DR
瞬态对象总是不同的;一个新的实例被提供给
每个控制器和每个服务。
作用域对象在请求中相同,但在请求中不同
不同的请求。
单个对象对于每个对象和每个请求都是相同的。
为了更清楚,.NET documentation 的这个例子显示了不同之处:
为了演示这些生命周期和注册选项之间的区别,请考虑一个简单的接口,它将一个或多个任务表示为具有唯一标识符 OperationId 的操作。根据我们如何配置此服务的生命周期,容器将为请求类提供相同或不同的服务实例。为了明确请求哪个生命周期,我们将为每个生命周期创建一个类型选项:
using System;
namespace DependencyInjectionSample.Interfaces
{
public interface IOperation
{
Guid OperationId { get; }
}
public interface IOperationTransient : IOperation
{
}
public interface IOperationScoped : IOperation
{
}
public interface IOperationSingleton : IOperation
{
}
public interface IOperationSingletonInstance : IOperation
{
}
}
我们使用单个类 Operation 实现这些接口,该类在其构造函数中接受 GUID,如果未提供则使用新的 GUID:
using System;
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Classes
{
public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
{
Guid _guid;
public Operation() : this(Guid.NewGuid())
{
}
public Operation(Guid guid)
{
_guid = guid;
}
public Guid OperationId => _guid;
}
}
接下来,在ConfigureServices中,每种类型都根据其命名的生命周期添加到容器中:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
请注意,IOperationSingletonInstance 服务正在使用已知 ID 为 Guid.Empty 的特定实例,因此在使用此类型时会很清楚。我们还注册了一个OperationService,它依赖于其他每个Operation 类型,这样在请求中就可以清楚地知道该服务是获取与控制器相同的实例还是新的实例,对于每个操作类型.该服务所做的只是将其依赖项作为属性公开,因此它们可以显示在视图中。
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Services
{
public class OperationService
{
public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance SingletonInstanceOperation { get; }
public OperationService(IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance instanceOperation)
{
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = instanceOperation;
}
}
}
为了演示对应用程序的单独请求内和之间的对象生命周期,示例包括一个OperationsController,它请求每种IOperation 类型以及一个OperationService。然后,Index 操作会显示所有控制器和服务的 OperationId 值。
using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;
using Microsoft.AspNetCore.Mvc;
namespace DependencyInjectionSample.Controllers
{
public class OperationsController : Controller
{
private readonly OperationService _operationService;
private readonly IOperationTransient _transientOperation;
private readonly IOperationScoped _scopedOperation;
private readonly IOperationSingleton _singletonOperation;
private readonly IOperationSingletonInstance _singletonInstanceOperation;
public OperationsController(OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance singletonInstanceOperation)
{
_operationService = operationService;
_transientOperation = transientOperation;
_scopedOperation = scopedOperation;
_singletonOperation = singletonOperation;
_singletonInstanceOperation = singletonInstanceOperation;
}
public IActionResult Index()
{
// ViewBag contains controller-requested services
ViewBag.Transient = _transientOperation;
ViewBag.Scoped = _scopedOperation;
ViewBag.Singleton = _singletonOperation;
ViewBag.SingletonInstance = _singletonInstanceOperation;
// Operation service has its own requested services
ViewBag.Service = _operationService;
return View();
}
}
}
现在向这个控制器动作发出两个单独的请求:
观察哪个OperationId 值在请求内和请求之间变化。
-
瞬态对象总是不同的;为每个控制器和每个服务提供一个新实例。
-
作用域对象在一个请求中是相同的,但在不同的请求中是不同的
-
每个对象和每个请求的单例对象都是相同的(不管ConfigureServices中是否提供了实例)