C#中的依赖注入Dependency Injection DI的实现步骤
目录
- 1. 基本概念
- 2. 配置依赖注入的步骤
- 步骤1:定义服务接口和实现类
- 步骤2:注册服务到容器
- 步骤3:注入服务到目标类
- 3. 在非Web应用(如wpF/控制台)中使用DI
- 4. 高级用法
- 4.1 注入多个实现(命名或策略模式)
- 4.2 使用工厂模式动态创建服务
- 4.3 生命周期管理注意事项
- 5. 常见问题解决
- 6. 总结表格
在C#中,依赖注入(Dependency Injection, DI)是一种实现控制反转(IoC)的设计模式,用于解耦组件依赖关系。以下是基于 .NET Core/ .NET 5+ 的依赖注入配置详细步骤和用法:
1. 基本概念
- 服务(Service):被注入的依赖项(如接口、类)。
- 容器(Container):管理服务的创建和生命周期(如
IServiceCollection
)。 - 生命周期:
- Transient:每次请求创建新实例。
- Scoped:同一作用域内共享实例(如一次HTTP请求)。
- Singleton:全局单例。
2. 配置依赖注入的步骤
步骤1:定义服务接口和实现类
// 定义接口 public interface IMyService { string GetMessage(); } // 实现接口 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:注入服务到目标类
通过构造函数注入:
public class MyController : ControllerBase { private readonly IMyService _service; // 构造函数自动注入 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) { www.devze.com var services = new ServiceCollection(); // 注册服务 services.AddTransient<IMyService, MyService>(); services.AddSingleton<MainWindow>(); // 注册主窗口SweRmFykP 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 注入多个实现(命名或策略模式)
// 注册多个实现 builder.Services.AddTransient<IjavascriptMyService, ServiceA>(); builder.Services.AddTransient<IMyService, ServiceB>(); // 通过 IEnumerable<T> 获取所有实现 public class Consumer { publiwww.devze.comc Consumer(IEnumerable<IMyService> services) { foreach (var service in services) { service.DOSomething(); } } }
4.2 使用工厂模式动态创建服务
builder.Services.AddTransient<IMyService>(provider => { var config = provider.GetRequiredService<IConfiguration>(); return new MyService(config.GetValue<string>("Mode")); });
4.3 生命周期管理注意事项
- 避免Singleton依赖Scoped服务:可能导致Captive Dependency问题。
- IDisposable处理:容器会自动释放实现了
IDisposable
的服务。
5. 常见问题解决
错误:未注册服务
System.InvalidOperationException: No service for type 'IMyService' has been registered.
解决:检查服务是否在 IServiceCollection
中正确注册。
循环依赖
重构代码以避免构造函数循环引用,或用Lazy<Tandroid>
延迟初始化。
6. 总结表格
操作 | 代码示例 | 说明 |
---|---|---|
注册Transient服务 | services.AddTransient<IMyService, MyService>(); | 每次请求新实例 |
注册Scoped服务 | services.AddScoped<IMyService, MyService>(); | 同一作用域内共享实例 |
注册Singleton服务 | services.AddSingleton<IMyService, MyService>(); | 全局单例 |
构造函数注入 | public MyClass(IMyService service) | 自动解析依赖 |
手动解析服务 | var service = provider.GetRequiredService<IMyService>(); | 从容器获取实例 |
通过以上步骤,可以灵活地在C#项目中配置和使用依赖注入,提升代码的可测试性和可维护性。
到此这篇关于C#中的依赖注入Dependency Injection DI的实现步骤的文章就介绍到这了,更多相关C# 依赖注入内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论