C#中的依賴注入Dependency Injection DI的實現(xiàn)步驟
在C#中,依賴注入(Dependency Injection, DI)是一種實現(xiàn)控制反轉(zhuǎn)(IoC)的設(shè)計模式,用于解耦組件依賴關(guān)系。以下是基于 .NET Core/ .NET 5+ 的依賴注入配置詳細步驟和用法:
1. 基本概念
- 服務(Service):被注入的依賴項(如接口、類)。
- 容器(Container):管理服務的創(chuàng)建和生命周期(如
IServiceCollection
)。 - 生命周期:
- Transient:每次請求創(chuàng)建新實例。
- Scoped:同一作用域內(nèi)共享實例(如一次HTTP請求)。
- Singleton:全局單例。
2. 配置依賴注入的步驟
步驟1:定義服務接口和實現(xiàn)類
// 定義接口 public interface IMyService { string GetMessage(); } // 實現(xiàn)接口 public class MyService : IMyService { public string GetMessage() => "Hello from MyService!"; }
步驟2:注冊服務到容器
在 Program.cs
或 Startup.cs
(.NET 6+ 通常使用 Program.cs
):
var builder = WebApplication.CreateBuilder(args); // 注冊服務(生命周期可選) builder.Services.AddTransient<IMyService, MyService>(); // 瞬時 builder.Services.AddScoped<IMyService, MyService>(); // 作用域 builder.Services.AddSingleton<IMyService, MyService>(); // 單例 // 直接注冊類(無接口) builder.Services.AddTransient<MyService>();
步驟3:注入服務到目標類
通過構(gòu)造函數(shù)注入:
public class MyController : ControllerBase { private readonly IMyService _service; // 構(gòu)造函數(shù)自動注入 public MyController(IMyService service) { _service = service; } [HttpGet] public IActionResult Get() { return Ok(_service.GetMessage()); } }
3. 在非Web應用(如WPF/控制臺)中使用DI
WPF 示例
安裝NuGet包:
Install-Package Microsoft.Extensions.DependencyInjection
配置DI容器(在 App.xaml.cs
):
public partial class App : Application { public IServiceProvider ServiceProvider { get; private set; } protected override void OnStartup(StartupEventArgs e) { var services = new ServiceCollection(); // 注冊服務 services.AddTransient<IMyService, MyService>(); services.AddSingleton<MainWindow>(); // 注冊主窗口 ServiceProvider = services.BuildServiceProvider(); // 解析主窗口并顯示 var mainWindow = ServiceProvider.GetRequiredService<MainWindow>(); mainWindow.Show(); } }
在窗口/ViewModel中注入:
public partial class MainWindow : Window { public MainWindow(IMyService service) { InitializeComponent(); var message = service.GetMessage(); // 使用注入的服務 } }
4. 高級用法
4.1 注入多個實現(xiàn)(命名或策略模式)
// 注冊多個實現(xiàn) builder.Services.AddTransient<IMyService, ServiceA>(); builder.Services.AddTransient<IMyService, ServiceB>(); // 通過 IEnumerable<T> 獲取所有實現(xiàn) public class Consumer { public Consumer(IEnumerable<IMyService> services) { foreach (var service in services) { service.DoSomething(); } } }
4.2 使用工廠模式動態(tài)創(chuàng)建服務
builder.Services.AddTransient<IMyService>(provider => { var config = provider.GetRequiredService<IConfiguration>(); return new MyService(config.GetValue<string>("Mode")); });
4.3 生命周期管理注意事項
- 避免Singleton依賴Scoped服務:可能導致Captive Dependency問題。
- IDisposable處理:容器會自動釋放實現(xiàn)了
IDisposable
的服務。
5. 常見問題解決
錯誤:未注冊服務
System.InvalidOperationException: No service for type 'IMyService' has been registered.
解決:檢查服務是否在 IServiceCollection
中正確注冊。
循環(huán)依賴
重構(gòu)代碼以避免構(gòu)造函數(shù)循環(huán)引用,或用 Lazy<T>
延遲初始化。
6. 總結(jié)表格
操作 | 代碼示例 | 說明 |
---|---|---|
注冊Transient服務 | services.AddTransient<IMyService, MyService>(); | 每次請求新實例 |
注冊Scoped服務 | services.AddScoped<IMyService, MyService>(); | 同一作用域內(nèi)共享實例 |
注冊Singleton服務 | services.AddSingleton<IMyService, MyService>(); | 全局單例 |
構(gòu)造函數(shù)注入 | public MyClass(IMyService service) | 自動解析依賴 |
手動解析服務 | var service = provider.GetRequiredService<IMyService>(); | 從容器獲取實例 |
通過以上步驟,可以靈活地在C#項目中配置和使用依賴注入,提升代碼的可測試性和可維護性。
到此這篇關(guān)于C#中的依賴注入Dependency Injection DI的實現(xiàn)步驟的文章就介紹到這了,更多相關(guān)C# 依賴注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#進行圖像處理的常見方法(Bitmap,BitmapData,IntPtr)使用詳解
這篇文章主要為大家詳細介紹了C#進行圖像處理的幾個常見方法(Bitmap,BitmapData,IntPtr)具體使用,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下2024-01-01C#使用is、as關(guān)鍵字以及顯式強轉(zhuǎn)實現(xiàn)引用類型轉(zhuǎn)換
這篇文章介紹了C#使用is、as關(guān)鍵字以及顯式強轉(zhuǎn)實現(xiàn)引用類型轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08Winform利用分頁控件實現(xiàn)導出PDF文檔功能
當前的Winform分頁控件中,當前導出的數(shù)據(jù)一般使用Excel來處理,但是有框架的使用客戶希望分頁控件能夠直接導出PDF,所以本文整理了一下分頁控件導出PDF的處理過程,分享一下2023-03-03