上一節介紹了依賴注入的基本用法,這節來了解依賴注入之生命週期
依賴注入有三個主要的生命週期,分別為
- Transient(暫時):每次請求服務時都會建立一個新的實例。
- Scoped(範圍):每一次 HTTP 請求都會建立一個實例,在該請求內部共用。
- Singleton(單例):整個應用程式生命週期只建立一次實例,所有請求共用同一個實例。
有以上三種依賴注入的模式,使用不同的依賴注入方式,就會有不同的生命週期
接著就來個別進行示範
第一個我們先使用Transient,並建立相關類別
DITransient.cs
namespace Kcg.Services
{
public class DITransient
{
public string value { get; set; }
public DITransient()
{
value = "Default";
}
}
}
接著我們就要到Program.cs進行依賴注入
builder.Services.AddTransient<DITransient>();
使用builder.Services.AddTransient
的類別,即會套用Transient的生命週期,跟你類別本身怎麼寫無關
接著我們就要controller跟service中取得該服務
private readonly DITransient _diTransient;
public NewsController(DITransient diTransient)
{
_diTransient = diTransient;
}
接著我們在controller和service中都使用DITransient
public async Task<IActionResult> Index()
{
_diTransient.value = _diTransient.value + ">controller";
var result = await _newsService.取得新聞列表();
ViewBag.DITransient = _diTransient.value;
return View(result);
}
public async Task<List<NewsDto>> 取得新聞列表()
{
_diTransient.value = _diTransient.value + ">service";
}
最後在View中印出ViewBag.DITransient看看值會是什麼
<div>
DITransient:@ViewBag.DITransient
</div>
這時候顯示會是

代表只有印出來的值是在controller設定的值,而service的值沒被設定到
原因就是Transient,每次取得服務時都是一個新的個體,也因此controller和service中的DITransient是不同的實例,兩者是獨立運作的
所以才會有顯示的結果
那這種Transient生命週期可以用在哪裡呢,就是你每個服務需要獨立,互不干擾的時候就可以使用
第二個我們使用Scoped,並建立相關類別
DIScoped.cs
namespace Kcg.Services
{
public class DIScoped
{
public string value { get; set; }
public DIScoped()
{
value = "Default";
}
}
}
接著我們就要到Program.cs進行依賴注入
builder.Services.AddScoped<DIScoped>();
然後我們一樣分別在controller和service同時取得服務並寫入值
最後結果如下

看起來controller和service中的值都有被設定到
原因就是Scoped是每次的http要求都共用同一個實例,因此controller和service中的DIScoped服務的變數都是共用的
所以如果同一次http我不怕這個服務裡的值互相干擾,且還可能有共用或互相取用的需求,並且只產生一次也節省資源
這時就可以使用Scoped,這也是最常使用的依賴注入方式,像我們資料庫物件就屬於這種模式
第三個來講Singleton,並建立相關類別,並且做好同樣的設定
此時會顯示如下

結果似乎跟Scoped一樣?但當我們再次重新整理的時候會發現

Singleton的值會一值增加,原因就是Singleton只在應用程式啟動的時候建立一次實例,之後用的都是同一支,因此值會一值存在到下次應用程式重啟的時候
那這樣的依賴注入模式,會適用於一個常用的服務,但卻不需要重複被建立,也可以節省資源
通常會用在一些不變的共用設定,我就開始取得設定檔後,大家就都使用這個服務,而這個服務因為常被使用且值不太會變動,所以也不需要每次重複產生並常駐著就很適合
那以上就是三種依賴注入的模式及生命週期的介紹,大家就可以依服務性質選用最適合的模式,那通常還沒仔細思考時,我們都會先用Scoped,算是裡面中庸的選擇
有特殊需求才會特別使用Transient和Singleton,算是分別為兩個極端的模式
範例檔:下載