关于ServiceLifetime(服务生命周期)中Transient与Scoped的理解
ServiceLifetime几种注入方式的解释:
- Transient:每次请求服务时,都会创建一个新实例,这种生命周期适合用于轻量级服务(如Repository和ApplicationService服务)。
- Scoped:为每个HTTP请求创建一个实例,生命周期将横贯整次请求。
- SingleTon:在第一次请求服务时,为该服务创建一个实例,之后每次请求将会使用第一次创建好的服务。
- Instance:与SingleTon类似,但在应用程序启动时会将该实例注册到容器中,可以理解为比SingleTon还早存在。
以下面的例子来理解:
建立一个拥有OperationId的接口IOperation,以不同方式注入IOperation打印出OperationId观察几种注入方式
public interface IOperation { Guid OperationId { get; } }
建立后期不同方式注入服务的接口
public interface ITransientOperation: IOperation { } public interface IScopedOperation: IOperation { }
接口实现
public class Operation : IOperation, ITransientOperation, IScopedOperation { private Guid operationId { get; set; } public Guid OperationId => operationId; public Operation(Guid id) { operationId = id; } public Operation():this(Guid.NewGuid()) { } }
注入服务
builder.Services.AddTransient<ITransientOperation, Operation>();
builder.Services.AddScoped<IScopedOperation, Operation>();
在建立一个实现了不同注入方式的服务的TestService,用以对比直接在请求中实现不同方式注入服务得到的结果,方便观察在同一请求中不同方式注服务的结果表现
public interface ITestService { public Guid TransientRes { get; set; } public Guid ScopeRes { get; set; } } public class TestService : ITestService { public readonly ITransientOperation _transientOperation; public readonly IScopedOperation _scopedOperation; public Guid TransientRes { get; set; } public Guid ScopeRes { get; set; } public TestService(ITransientOperation transientOperation, IScopedOperation scopedOperation) { _transientOperation = transientOperation; _scopedOperation = scopedOperation; TransientRes = _transientOperation.OperationId; ScopeRes = _scopedOperation.OperationId; } }
Controller调用
[ApiController] [Route("controller")] public class UserController : ControllerBase { private readonly ITestService _testService; private ITransientOperation _transientOperation; private IScopedOperation _scopedOperation; public UserController( ITestService testService, ITransientOperation transientOperation, IScopedOperation scopedOperation) { _testService = testService; _transientOperation = transientOperation; _scopedOperation = scopedOperation; } [HttpGet("TestServiceOfLifeTime")] public TestResult TestService() { var res=new TestResult(); res.TransientResult = _transientOperation.OperationId; res.ScopedResult = _scopedOperation.OperationId; res.TSTransientResult = _testService.TransientRes; res.TSScopedResult = _testService.ScopeRes; return res; } }
两次请求的结果
第一次请求结果
第二次请求结果
以上可观察到Scoped在每一次请求中不论是TestService中的服务还是在Controller中的实现的服务,OperationId都是一样的,但不同的请求是不一样的,表示在同一个请求中Scoped服务始终保持一个实例
Transient在同一请求中Controller的实现与TestService中的实现中OperationId都是不一样的,不同的请求也是不一样的,表示Transient在每一次的实现都是一个新的实例