前言
依賴注入(Dependency Injection, DI) 是一種實現控制反轉(Inversion of Control, IoC) 的軟件設計模式,也是構建鬆耦合、可測試、易維護應用程序的核心技術。其核心理念是:不要在類內部創建依賴,而是由外部容器將依賴注入進來。
在現代 ASP.NET Core 中內置了強大的 DI 容器,正確使用 DI 的關鍵在於理解 Transient、Scoped 和 Singleton 這三種服務生命週期,它們決定了服務實例的創建時機、共享範圍與生命週期。本文將清晰解析三者的區別和適用場景。
簡單概述
在 ASP.NET Core 中,依賴注入容器通過IServiceCollection支持三種服務註冊生命週期:
IServiceCollection 是 .NET 依賴注入(DI)系統中的核心接口之一,用於註冊和管理應用程序所需的服務。
|
生命週期
|
註冊方法
|
實例創建時機
|
共享範圍
|
|
Transient(瞬態)
|
|
每次請求都創建新實例
|
不共享
|
|
Scoped(作用域)
|
|
每個作用域(如 HTTP 請求)創建一次
|
在同一作用域內共享
|
|
Singleton(單例)
|
|
應用啓動時創建一次(或首次使用時)
|
整個應用生命週期共享
|
選型口訣
- 跨請求共享、需複用 → Singleton(線程安全要做好)
- 請求內共享、一致性、上下文傳遞 → Scoped
- 一次性、無狀態、輕量 → Transient
Transient(瞬態)
每次從 DI 容器請求服務時,都會創建一個全新的實例。
適用場景
- 輕量級、無狀態的服務。
- 請求級獨立狀態:每次調用需要獨立狀態或副作用隔離的組件。
- 短生命週期依賴鏈:依賴鏈中各服務都很輕、無共享資源的場景。
Scoped(作用域)
在同一個作用域內共享同一個實例,不同作用域創建不同實例。
在 ASP.NET Core 中,每個 HTTP 請求就是一個作用域。
適用場景
- 需要在單次請求中共享狀態的服務。
- 數據庫上下文(DbContext):AddDbContext() 默認註冊為 Scoped,保證同一 HTTP 請求內複用同一個數據庫上下文,避免實體跟蹤混亂、重複連接開銷,並支持事務一致性。
- 工作單元(Unit of Work)與數據倉儲(Repository):與 DbContext 同生命週期,保障查詢→修改→提交的一致性,並減少資源創建銷燬。
Singleton(單例)
整個應用程序生命週期內只創建一次實例,所有請求共享同一個對象。
適用場景
- 無狀態、線程安全的全局服務(如工具類、映射器)。
- 配置封裝服務(如 IAppSettings),啓動後內容不變。
- 全局緩存(如 IMemoryCache),需跨請求共享數據。
參考文章
- https://learn.microsoft.com/zh-cn/dotnet/core/extensions/dependency-injection#service-lifetimes