選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
4 分鐘閱讀時間 (753 個字)

[.Net Core] 服務存留期 (Service Lifetime)

unsplash-coding104

在 .Net 及 .Net Core 的相依注入 (Dependency Injection) 中,
服務可以被註冊成以下三種存留期:

  • Transient
  • Scoped
  • Singleton

下面跟大家介紹這三種存留期的特性,及如何選擇該使用的存留期。

 Transient (暫時性)

public class Startup
{

	// ...
	
	public void ConfigureServices(IServiceCollection services)
  {
		// 註冊 SampleService 為 SampleService
		services.AddTransient(typeof(SampleService));

		services.AddTransient<SampleService>();

		services.AddTransient(serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());

		// 註冊 ISampleService 為 SampleService
		services.AddTransient(typeof(ISampleService), typeof(SampleService));

		services.AddTransient(typeof(ISampleService), serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());

		services.AddTransient<ISampleService, SampleService>();

		services.AddTransient<ISampleService>(serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());
	}

	// ...
} 

被註冊為 Transient 的服務,會在每次向 Container 請求注入時,建立一個新的實例

也就是說,假設 A 及 B 都有注入被註冊為 Transient 的 C Service,
則注入到 A 和 B 中的 C Service 會是兩個不同的實例。

Transient 的實例會在每次請求結束後被 Dispose。

註冊成 Transient 的服務,存留時間短,適合輕量、無狀態 (Stateless) 的服務。

 Scoped (範圍性)

public class Startup
{

	// ...
	
	public void ConfigureServices(IServiceCollection services)
  {
		// 註冊 SampleService 為 SampleService
		services.AddScoped(typeof(SampleService));

		services.AddScoped<SampleService>();

		services.AddScoped(serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());

		// 註冊 ISampleService 為 SampleService
		services.AddScoped(typeof(ISampleService), typeof(SampleService));

		services.AddScoped(typeof(ISampleService), serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());

		services.AddScoped<ISampleService, SampleService>();

		services.AddScoped<ISampleService>(serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());
	}

	// ...
} 

Scoped 是針對 Web 應用程式使用的存留期。

被註冊為 Scoped 的服務,會在每個客戶端請求連線時,建立一個新的實例

也就是說,假設 A 及 B 都有注入被註冊為 Scoped 的 C Service,
則在處理同一個 API Request 時,注入到 A 和 B 中的 C Service 會是相同的實例;

但在處理另一個 API Request 時,注入的 C Service 會是不同的實例。

Scoped 的實例同樣會在每次請求結束後被 Dispose。

註冊成 Scoped 的服務,存留時間和客戶端請求相同,適合針對個別請求有不同狀態的服務。

 Singleton (單一性)

public class Startup
{

	// ...
	
	public void ConfigureServices(IServiceCollection services)
  {
		// 註冊 SampleService 為 SampleService
		services.AddSingleton(typeof(SampleService));

		services.AddSingleton<SampleService>();

		services.AddSingleton(serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());

		services.AddSingleton(new SampleService()); // 直接提供實例給Container

		// 註冊 ISampleService 為 SampleService
		services.AddSingleton(typeof(ISampleService), typeof(SampleService));

		services.AddSingleton(typeof(ISampleService), serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());

		services.AddSingleton(
			typeof(ISampleService), new SampleService()); // 直接提供實例給Container

		services.AddSingleton<ISampleService, SampleService>();

		services.AddSingleton<ISampleService>(serviceProvider =>
			new SampleService(serviceProvider.GetService<SampleInjectService>());
	}

	// ...
} 

被註冊為 Singleton 的服務,會在第一次向 Container 請求注入時,建立一個新的實例
(或者是由開發者直接向 Container 提供一個實例)

在實例產生後,應用程式中的每一個注入請求,都會使用同一個實例。

也就是說,只要在同一個應用程式中注入的 C Service 都會是相同的實例。

當應用程式結束、 ServiceProvider 被 Dispose 時,實例才會被 Dispose。

註冊成 Singleton 的服務,存留時間和應用程式相同,適合需要在應用程式執行期間維持狀態的服務。

 Singleton 和 Scoped 的限制

由於 Scoped 存留期是根據客戶端請求的長度,

故不能在 "註冊為 Singleton 的服務" 中注入 "註冊為 Scoped 的服務"

亦不可透過註冊為 Transient 的服務,間接注入註冊為 Scoped 的服務。

(Ex. 在 Singleton 服務中注入 "註冊為 Transient 但注入 Scoped 服務" 的服務)

PWA - Service Worker Register
[Data Modeling] Recursive Pattern

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/05/12, 週日

Captcha 圖像