1. 什麼是依賴注入 (Dependency Injection)?
在現代化的軟體開發中,依賴注入 (DI) 是一種非常重要的設計模式,它主要用於實現控制反轉 (IoC)。 簡單來說,就是「不要自己 new 物件,讓別人幫你 new 好送進來」。這樣可以大幅降低程式碼之間的耦合度 (Coupling), 讓系統更容易測試與維護。
"High cohesion, low coupling (高內聚,低耦合)" 是軟體架構設計的黃金準則。
2. 生命週期介紹
在 ASP.NET Core 中,內建的 DI 容器提供了三種主要的生命週期,這也是面試時最常被問到的考題:
- Transient (暫時的):每次請求服務時,都會建立一個新的實例。輕量級無狀態服務適合使用。
- Scoped (範圍的):在同一個 HTTP Request 範圍內,只會建立一個實例。最常用於資料庫 Context。
- Singleton (單例的):在整個應用程式啟動到結束,只會有一個實例。適合快取服務。
3. 程式碼實作範例
讓我們來看看如何在 `Program.cs` 中註冊這些服務。以下是一段標準的註冊代碼:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// 1. 註冊 Transient 服務
builder.Services.AddTransient();
// 2. 註冊 Scoped 服務 (通常用於 DB Context)
builder.Services.AddScoped();
// 3. 註冊 Singleton 服務 (快取)
builder.Services.AddSingleton();
var app = builder.Build();
接著,我們可以在 Controller 的建構子 (Constructor) 中直接注入使用:
// HomeController.cs
public class HomeController : Controller
{
private readonly IEmailService _emailService;
// 透過建構子注入 (Constructor Injection)
public HomeController(IEmailService emailService)
{
_emailService = emailService;
}
public IActionResult Index()
{
_emailService.Send("Test Email");
return View();
}
}
4. 常見的錯誤陷阱
在使用 DI 時,最致命的錯誤就是「在 Singleton 服務中注入 Scoped 服務」 (Captive Dependency)。 這會導致 Scoped 服務原本應該跟著 Request 結束而釋放,卻因為被 Singleton 抓住而無法釋放,最終導致記憶體洩漏 (Memory Leak) 或資料庫連線錯誤。
5. 結論
掌握依賴注入是成為資深 .NET 開發者的必經之路。它不只是一種語法,更是一種架構思維。 希望這篇文章能幫助大家釐清觀念。如果您想深入學習如何設計乾淨架構 (Clean Architecture),歡迎報名我們的進階課程!