在ConfigureServices方法中的容器註冊每一個應用程序的服務,Asp.Core均可覺得每一個應用程序提供三種服務生命週期:
●Transient(暫時):每次請求都會建立一個新的實例。這種生命週期最適合輕量級,無狀態服務。
●Scoped(做用域):在同一個做用域內只初始化一個實例 ,能夠理解爲每個請求只建立一個實例,同一個請求會在一個做用域內。
●Singleton(單例):整個應用程序生命週期之內只建立一個實例,後續每一個請求都使用相同的實例。若是應用程序須要單例行爲,建議讓服務容器管理服務的生命週期,而不是在本身的類中實現單例模式。ui
爲了演示生命週期和註冊選項之間的差別,請考慮如下接口,將任務表示爲具備惟一標識符 OperationId 的操做。根據如下接口配置操做服務的生命週期的方式,容器在類請求時提供相同或不一樣的服務實例:this
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類的實現:spa
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類實例的做用域變化。3d
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()服務容器中註冊各個生命週期的實例:code
public void ConfigureServices(IServiceCollection services) { 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>(); }
再在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 類輸出結果:blog
由圖總結以下:
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中只實例化一次實例,常見的單例模式。作用域
參考文獻:
在ASP.NET Core依賴注入