(3)ASP.NET Core 服务生命周期 1. 前言
在 ConfigureServices 方法中的容器注册每个应用程序的服务, Asp.Core 都可以为每个应用程序提供三种服务生命周期:
2. 服务生命周期与注册选项案例演示
为了演示生命周期和注册选项之间的差异, 请考虑以下接口, 将任务表示为具有唯一标识符 OperationId 的操作. 根据以下接口配置操作服务的生命周期的方式, 容器在类请求时提供相同或不同的服务实例:
- public interface IOperation
- {
- Guid OperationId { get; }
- }
- public interface IOperationTransient : IOperation
- {
- }
- public interface IOperationScoped : IOperation
- {
- }
- public interface IOperationSingleton : IOperation
- {
- }
- public interface IOperationSingletonInstance : IOperation
- {
- }
上面四种服务接口在 Operation 类中实现. 调用 Operation 类时将自动生成一个 GUID, 下面是 Operation 类的实现:
- public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
- {
- public Operation() : this(Guid.NewGuid())
- {
- }
- public Operation(Guid id)
- {
- OperationId = id;
- }
- public Guid OperationId { get; private set; }
- }
再注册一个 OperationService 服务实例, 当通过依赖关系注入请求 OperationService 实例时, 它将接收每个服务的新实例或基于从属服务 (Operation) 的生命周期的现有实例. OperationService 服务作用就是第二次调用 Operation 类, 查看 Operation 类实例的作用域变化.
- public class OperationService
- {
- public OperationService(
- IOperationTransient transientOperation,
- IOperationScoped scopedOperation,
- IOperationSingleton singletonOperation,
- IOperationSingletonInstance instanceOperation)
- {
- _transientOperation = transientOperation;
- _scopedOperation = scopedOperation;
- _singletonOperation = singletonOperation;
- _singletonInstanceOperation = instanceOperation;
- }
- public IOperationTransient _transientOperation { get; }
- public IOperationScoped _scopedOperation { get; }
- public IOperationSingleton _singletonOperation { get; }
- public IOperationSingletonInstance _singletonInstanceOperation { get; }
- }
然后在 Startup.ConfigureServices()服务容器中注册各个生命周期的实例:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddTransient();
- services.AddScoped();
- services.AddSingleton();
- services.AddSingleton(new Operation(Guid.Empty));
- // OperationService depends on each of the other Operation types.
- services.AddTransient();
- }
再在 IndexModel 模块里面调用 OnGet 方法输出, 观察 IOperation 与 OperationService 类属性 OperationId 值的变化:
- public class IndexModel : PageModel
- {
- public OperationService _operationService { get; }
- public IOperationTransient _transientOperation { get; }
- public IOperationScoped _scopedOperation { get; }
- public IOperationSingleton _singletonOperation { get; }
- public IOperationSingletonInstance _singletonInstanceOperation { get; }
- public IndexModel(
- OperationService operationService,
- IOperationTransient transientOperation,
- IOperationScoped scopedOperation,
- IOperationSingleton singletonOperation,
- IOperationSingletonInstance singletonInstanceOperation)
- {
- _operationService = operationService;
- _transientOperation = transientOperation;
- _scopedOperation = scopedOperation;
- _singletonOperation = singletonOperation;
- _singletonInstanceOperation = singletonInstanceOperation;
- }
- public void OnGet()
- {
- Console.WriteLine("IOperation 操作:");
- Console.WriteLine("暂时:" + _transientOperation.OperationId.ToString());
- Console.WriteLine("作用域:" + _scopedOperation.OperationId.ToString());
- Console.WriteLine("单例:" + _singletonOperation.OperationId.ToString());
- Console.WriteLine("实例:" + _singletonInstanceOperation.OperationId.ToString());
- Console.WriteLine("OperationService 操作:");
- Console.WriteLine("暂时:" + _operationService._transientOperation.OperationId.ToString());
- Console.WriteLine("作用域:" + _operationService._scopedOperation.OperationId.ToString());
- Console.WriteLine("单例:" + _operationService._singletonOperation.OperationId.ToString());
- Console.WriteLine("实例:" + _operationService._singletonInstanceOperation.OperationId.ToString());
- }
- }
执行 IndexModel 类输出结果:
由图总结如下:
2.1 Transient(暂时): 每次调用服务的时候都会创建一个新的实例. 即在 IndexModel 类的局部方法或属性中 (这里是 OnGet 方法) 实例化一个依赖对象 Operation 类, 伪代码是:
- public class IndexModel: PageModel
- {
- public void OnGet()
- {
- // 调用 IndexModel 类时, 实例化了两次 Operation 类
- // 第一次
- OperationService operationService=new OperationService();
- // 第二次
- IOperationTransient TransientOperation=new Operation();
- }
- }
2.2 Scoped(作用域): 一次请求 (Action) 内对象实例是相同的, 但每次请求会产生一个新实例. 相当于在 IndexModel 类的全局中实例化一次依赖对象 Operation 类, 伪代码是:
- OperationService operationService = null;
- public IndexModel()
- {
- operationService = new OperationService();
- operationService._scopedOperation = new Operation();
- }
- public void OnGet()
- {
- operationService._scopedOperation.OperationId;
- IOperationScoped operationScoped = operationService._scopedOperation;
- operationScoped.OperationId
- }
2.3 Singleton(单例): 首次请求初始化同一个实例, 后续每次请求都使用同一个实例. 相当于在整个应用 Application 中只实例化一次实例, 常见的单例模式.
参考文献:
来源: https://www.2cto.com/kf/201905/809341.html