ASP.NET Core服務(wù)生命周期
1.前言
在ConfigureServices方法中的容器注冊每個應(yīng)用程序的服務(wù),Asp.Core都可以為每個應(yīng)用程序提供三種服務(wù)生命周期:
- Transient(暫時):每次請求都會創(chuàng)建一個新的實例。這種生命周期最適合輕量級,無狀態(tài)服務(wù)。
- Scoped(作用域):在同一個作用域內(nèi)只初始化一個實例 ,可以理解為每一個請求只創(chuàng)建一個實例,同一個請求會在一個作用域內(nèi)。
- Singleton(單例):整個應(yīng)用程序生命周期以內(nèi)只創(chuàng)建一個實例,后續(xù)每個請求都使用相同的實例。如果應(yīng)用程序需要單例行為,建議讓服務(wù)容器管理服務(wù)的生命周期,而不是在自己的類中實現(xiàn)單例模式。
2.服務(wù)生命周期與注冊選項案例演示
為了演示生命周期和注冊選項之間的差異,請考慮以下接口,將任務(wù)表示為具有唯一標(biāo)識符 OperationId 的操作。根據(jù)以下接口配置操作服務(wù)的生命周期的方式,容器在類請求時提供相同或不同的服務(wù)實例:
public interface IOperation
{
Guid OperationId { get; }
}
public interface IOperationTransient : IOperation
{
}
public interface IOperationScoped : IOperation
{
}
public interface IOperationSingleton : IOperation
{
}
public interface IOperationSingletonInstance : IOperation
{
}上面四種服務(wù)接口在 Operation 類中實現(xiàn)。調(diào)用Operation類時將自動生成一個GUID,下面是Operation類的實現(xiàn):
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服務(wù)實例,當(dāng)通過依賴關(guān)系注入請求 OperationService 實例時,它將接收每個服務(wù)的新實例或基于從屬服務(wù)(Operation)的生命周期的現(xiàn)有實例。OperationService 服務(wù)作用就是第二次調(diào)用 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()服務(wù)容器中注冊各個生命周期的實例:
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模塊里面調(diào)用OnGet方法輸出,觀察IOperation與OperationService類屬性O(shè)perationId 值的變化:
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());
}
}執(zhí)行IndexModel 類輸出結(jié)果:

由圖總結(jié)如下:
2.1 Transient(暫時):每次調(diào)用服務(wù)的時候都會創(chuàng)建一個新的實例。即在IndexModel類的局部方法或?qū)傩灾校ㄟ@里是OnGet方法)實例化一個依賴對象Operation類,偽代碼是:
public class IndexModel: PageModel
{
public void OnGet()
{
//調(diào)用IndexModel類時,實例化了兩次Operation類
//第一次
OperationService operationService=new OperationService();
//第二次
IOperationTransient TransientOperation=new Operation();
}
}2.2 Scoped(作用域):一次請求(Action)內(nèi)對象實例是相同的,但每次請求會產(chǎn)生一個新實例。相當(dāng)于在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(單例):首次請求初始化同一個實例,后續(xù)每次請求都使用同一個實例。相當(dāng)于在整個應(yīng)用Application中只實例化一次實例,常見的單例模式。
生命周期流程圖如下:

到此這篇關(guān)于ASP.NET Core服務(wù)生命周期的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解.net循環(huán)、邏輯語句塊(基礎(chǔ)知識)
本篇是介紹.NET 基礎(chǔ)部分,主要簡述循環(huán),判斷,對初學(xué)者具有很好的參考借鑒價值,下面就跟小編一起來看下吧2016-12-12
.Net?Core微服務(wù)rpc框架GRPC通信實際運用
這篇文章介紹了.Net?Core微服務(wù)rpc框架GRPC通信實際運用,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01

