简单介绍,直接官方文档
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2
public interface IOperation {Guid OperationId { get; } }public interface IOperationTransient : IOperation { }public interface IOperationScoped : IOperation { }public interface IOperationSingleton : IOperation { }public interface IOperationSingletonInstance : IOperation { }
public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance {public Operation() : this(Guid.NewGuid()){}public Operation(Guid id){OperationId = id;}public Guid OperationId { get; private set; } }
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 中,根据其指定的生存期,将每个类型添加到容器中: C#public void ConfigureServices(IServiceCollection services) {services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);services.AddScoped<IMyDependency, MyDependency>();services.AddTransient<IOperationTransient, Operation>();services.AddScoped<IOperationScoped, Operation>();services.AddSingleton<IOperationSingleton, Operation>();services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));// OperationService depends on each of the other Operation types.services.AddTransient<OperationService, OperationService>(); }
public class IndexModel : PageModel {private readonly IMyDependency _myDependency;public IndexModel(IMyDependency myDependency, OperationService operationService,IOperationTransient transientOperation,IOperationScoped scopedOperation,IOperationSingleton singletonOperation,IOperationSingletonInstance singletonInstanceOperation){_myDependency = myDependency;OperationService = operationService;TransientOperation = transientOperation;ScopedOperation = scopedOperation;SingletonOperation = singletonOperation;SingletonInstanceOperation = singletonInstanceOperation;}public OperationService OperationService { get; }public IOperationTransient TransientOperation { get; }public IOperationScoped ScopedOperation { get; }public IOperationSingleton SingletonOperation { get; }public IOperationSingletonInstance SingletonInstanceOperation { get; }public async Task OnGetAsync(){await _myDependency.WriteMessage("IndexModel.OnGetAsync created this message.");} }
以下两个输出显示了两个请求的结果:
第一个请求:
控制器操作:
暂时性:d233e165-f417-469b-a866-1cf1935d2518
作用域:5d997e2d-55f5-4a64-8388-51c4e3a1ad19
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
OperationService
操作:
暂时性:c6b049eb-1318-4e31-90f1-eb2dd849ff64
作用域:5d997e2d-55f5-4a64-8388-51c4e3a1ad19
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
第二个请求:
控制器操作:
暂时性:b63bd538-0a37-4ff1-90ba-081c5138dda0
作用域:31e820c5-4834-4d22-83fc-a60118acb9f4
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
OperationService
操作:
暂时性:c4cbacb8-36a2-436d-81c8-8c1b78808aaf
作用域:31e820c5-4834-4d22-83fc-a60118acb9f4
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
观察哪个 OperationId
值会在一个请求之内和不同请求之间变化:
- 暂时性 对象始终不同。 第一个和第二个客户端请求的暂时性
OperationId
值对于OperationService
操作和在客户端请求内都是不同的。 为每个服务请求和客户端请求提供了一个新实例。 - 作用域 对象在一个客户端请求中是相同的,但在多个客户端请求中是不同的。
- 单一实例 对象对每个对象和每个请求都是相同的(不管
Startup.ConfigureServices
中是否提供Operation
实例)。
- 暂时性 对象始终不同。 第一个和第二个客户端请求的暂时性
接下来是本文重点要说明的
public void ConfigureServices(IServiceCollection services) {services.AddSingleton<SingletonService>();services.AddTransient<TransientService>();services.AddScoped<ScopedService>(); }
public class SingletonService{public string Id = Guid.NewGuid().ToString();}public class ScopedService{public string Id = Guid.NewGuid().ToString();}public class TransientService{public string Id = Guid.NewGuid().ToString();private ScopedService _transient;private SingletonService _singleton;public TransientService(ScopedService transient, SingletonService singleton){_transient = transient;_singleton = singleton;}}
这种情况是可以的,transient 可以依赖 singleton 和 scoped
对于 Transient 服务,它可以被任何服务依赖,但是在依赖的服务中创建的服务的生命周期会跟随依赖的服务
对于 Scoped 服务,它只能被 Transient 和 Scoped 服务依赖,生命周期不会变化,如果要在 Singleton 服务中使用,可以使用 IServiceProvider 的 CreateScope 方法 ,然后 GetService, 但是 生成的 scoped 服务生命周期为 Singleton
对于 Singleton 服务,它可以被任何服务依赖,生命周期不会变化
public class SingletonService{public string Id = Guid.NewGuid().ToString();private ScopedService _scoped;public SingletonService(IServiceProvider serviceProvider){using (var scope = serviceProvider.CreateScope()){_scoped = scope.ServiceProvider.GetService<ScopedService>();}}}public class ScopedService{public string Id = Guid.NewGuid().ToString();}public class TransientService{public string Id = Guid.NewGuid().ToString();}
这个 在单例中使用 Scoped 服务