.Net 6 Dependency Injection

控制反轉是物件導向開發中重要的軟體開發設計模式,.net 框架中也有實現這項技術。

Joe Chiu
appxtech
Published in
5 min readApr 10, 2023

--

高階模組依賴於抽象介面與實作細節解耦,低階模組轉而依賴高階模組的需求抽象。被依賴的物件只需要由服務容器來建立,不用我們手動建立,由服務容器來管理物件的生成和銷毀。

.net 框架中 有2種方法實現控制反轉

service locator — 在程式中主動向服務容器索取

dependency injection — 在物件生成時,服務容器在建構式注入到物件私有成員

服務留存期 ( Service Lifetime )

  1. Singleton : 整個 Process 只建立一個 Instance,任何時候都共用它。
  2. Scoped : 在網頁 Request 處理過程共用一個 Instance。(接到瀏覽器請求到回傳結果前的執行期間)
  3. Transient : 每次要求元件時就建立一個新的,永不共用。

參考 黑暗執行緒筆記 : https://blog.darkthread.net/blog/aspnet-core-di-notes/

Console App 中 實作 IOC

這次的範例是用 service locator 方法,在微軟的官方文檔中有明確寫道,不建議使用這種方法取得物件,建議使用 DI依賴注入,在註冊服務時也建議使用抽象介面,依賴於抽象達到依賴反轉。

範例:

Program.cs

  1. Install Nuget package & using
  • Microsoft.Extensions.DependencyInjection

2. new ServiceCollection()

3. 註冊到 service container

  • AddSingleton
  • AddScoped
  • AddTransient

4. using ServiceProvider

using Microsoft.Extensions.DependencyInjection;
namespace Ioc;
class Program
{
static void Main(string[] args)
{
ServiceCollection service = new ServiceCollection();
// service.AddSingleton<TestService>();
// service.AddScoped<TestService>();
service.AddTransient<TestService>();
using (ServiceProvider serviceProvider = service.BuildServiceProvider())
{
TestService t1 = serviceProvider.GetService<TestService>();
TestService t2 = serviceProvider.GetService<TestService>();
t1.Name = "小明";
t2.Name = "小華";
t1.SayHi();
t2.SayHi();
Console.WriteLine("是否為相同物件: " + Object.ReferenceEquals(t1, t2));
}
}
}

TestService.cs

  • Add interface
  • Add class
namespace Ioc;
public interface ITestService
{
public string Name { get; set; }
public void SayHi();
}

public class TestService : ITestService
{
public string Name { get; set; } = "";
public void SayHi()
{
Console.WriteLine($"Hi, 我是{Name}");
}
}

執行結果

AddSingleton

AddScoped

AddTransient

與我想像中的相同,Singleton和Scoped會得到相同的物件,Transient會得到不同的物件。

參考 楊中科 微軟MVP .net 教程範例:https://www.youtube.com/watch?v=iEeyxFQeYYI&list=PL9sJKk6XPMxehYCui7OysUV6trlBbJ4T_&index=35&ab_channel=杨中科

小結:

Singleton 整個 Application 共用同一個實體適合無狀態的服務,Scoped 在一個 Request 中會注入一個新的實體,不會在不同 Request 中共用,可以作為有狀態的服務,Transient 會在每次注入中都是注入新的實體,就會佔用到比較多的記憶體。

另外 Scoped 有延伸可以客製化 scope 的方法,所以再一次請求中如果劃分不同的 scope 那也可以獲得到不同的實體。

參考: ATai IT邦幫忙微軟官方文檔

--

--