.Net Core DI 服務生命週期

Scoped:每次Post/Get Request在Application結束前,都會使用相同的instance

Transient:每次注入都會建立新的instance

Singleton:應用程式從開始到結束,使用的都是同一個instance。(ex:執行應用程式後,會先進入Program,接著執行Post/Get Request,接著再執行一次Post/Get Request。這種情況使用的都是同一個Service實體。第二次Post/Get Request不會再進入Program,不算Application結束)。

  • 模擬測試情境如下:

TestController.cs

IExcelService excelService,
MainService mainService

/*建構子先注入兩個Service*/
public TestController(IExcelService _excelService, MainService _mainService)
{
	_excelService = excelService;
	_mainService = mainService;
}
 
[HttpPost]
public async Task<Result<string>> DataCheck([FromBody] ReqGetDiffList data)
{	
	var hashCode = _excelService.GetHashCode(); //get HashCode
    var excelData = await _excelService.ReadExcel("TEST_PATH", null);	//_excelService.ReadExcel()會先讀取Excel並把回傳值給_mainService.ProcessExcelData做資料處理。
	
    try
    {
    	var eqmStock = await _mainService.ProcessExcelData(data.FilterFileType, null, null, _optEmployeeIdSettings, "TEST_PATH", excelData);
	}
    catch (Exception)
    {}
            
	......省略......    
}

MainService.cs

/*建構子注入IExcelService的實體*/
public MainService(IExcelService _excelService)
{
	_excelService = excelService;
}

public async Task<Result<string>> ProcessExcelData(DataTable excelData)
{	
	var hashCode = _excelService.GetHashCode();     //get HashCode 
	......省略......    
}

由上面程式碼可以看到ExcelService分別於兩個class被注入。


  • Scoped測試如下

先用AddScoped註冊Service對應

在TestController.cs底下的_excelService的HashCode為[28137373]

在MainService.cs底下的_excelService的HashCode為[28137373]

如果再重新呼叫一次DataCheck(重新發送一個新的Request),TestController.cs底下的_excelService的HashCode為就又會更新成[30544512]了
 

由於是同一個Request,所以MainService.cs底下的_excelService.HashCode則會跟TestController下的_excelService.HashCode一樣為[30544512]

從上面測試可以看出來,在同個應用程式Runtime之下,即使IExcelService在分別被TestController跟MainService被注入。但在相同的Request下,所取得的HashCode的值還是一樣,也表示_excelService用的是同一個instance。


  • Transient測試如下

先用AddTransient註冊Service對應

在TestController.cs底下的_excelService的HashCode為[26096572]

在MainService.cs底下的_excelService的HashCode為[63555393]

 

從上面測試可以看出來,在同個應用程式Runtime以及同個Request之下,由於IExcelService在分別被TestController跟MainService被注入。所以取得的HashCode的值會不一樣,也表示_excelService在TestController跟MainService用的是不同instance。但反過來說,如果MainService還有其他地方也要用到_excelService的話,那就會是一樣的instance,因為是從同一個建構子注入的。


  • Singleton測試如下

先用AddSingleton註冊Service對應

在TestController.cs底下的_excelService的HashCode為[66500315]

在MainService.cs底下的_excelService的HashCode為[66500315]

重新發送一個新的Request,在TestController.cs底下的_excelService的HashCode還是一樣為[66500315]

重新發送一個新的Request,在MainService.cs底下的_excelService的HashCode還是一樣為[66500315]

 

由上面的測試可以看到Singleton就比較單純了,不管Request的發送次數或是由注入次數,只要是同一個Runtime之下,都是使用同一個instance。


另外要注意的是,如果高階模組的服務生命週期為Singleton,那麼被注入的模組的服務生命週期就不能為Scoped,否則式會報錯的。以上面的例子來看MainService(高階模組)注入了ExcelService(低階模組),那麼如果MainService的服務生命週期為Singleton,ExcelService的服務生命週期就不能為Scoped。

Ref:
1.【Asp.Net Core】生命週期
2. [Day04] 依賴注入 (Dependency Injection) - 我與 ASP.NET Core 3 的 30天