马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
原为链接:https://www.cnblogs.com/ysmc/p/18796964
.NET 依赖注入深入详解
依赖注入(Dependency Injection, DI)是.NET Core .NET 5/6/7/8/9/10+中最重要的设计模式之一,下面我将从多个维度具体解释它的工作原理和使用方法。
一、核心概念剖析
1. 什么是依赖?
当一个类A必要类B才能正常工作时,我们就说类A"依赖"于类B。比方:- public class OrderService
- {
- private readonly ILogger _logger; // OrderService依赖于ILogger
-
- public OrderService(ILogger logger)
- {
- _logger = logger;
- }
- }
复制代码 2. 传统方式的题目
没有DI时,我们可能会如许写:- public class OrderService
- {
- private readonly FileLogger _logger = new FileLogger(); // 直接创建具体实现
-
- // ...
- }
复制代码 这种方式的缺点:
- 紧耦合:OrderService直接依赖FileLogger
- 难以测试:无法轻松替换为测试用的Logger
- 难以修改:如果要改用DatabaseLogger,必要修改OrderService代码
二、.NET DI 容器详解
1. 服务注册方式
在Program.cs/Startup.cs中有三种主要注册方式:- // 1. 注册具体类型
- services.AddTransient<EmailService>();
- // 2. 注册接口-实现映射
- services.AddScoped<IEmailService, SmtpEmailService>();
- // 3. 注册现有实例
- var logger = new FileLogger();
- services.AddSingleton<ILogger>(logger);
复制代码 2. 生命周期详解
生命周期形貌适用场景示例Transient每次请求都创建新实例轻量级、无状态服务工具类、DTO映射Scoped同一请求内共享实例必要请求上下文的服务DbContext、用户会话Singleton整个应用生命周期一个实例全局共享资源配置、缓存、日记
3. 高级注册技巧
- // 注册多个实现
- services.AddTransient<IMessageService, SmsService>();
- services.AddTransient<IMessageService, EmailService>();
- // 命名注册
- services.AddTransient<IMessageService>("SMS", typeof(SmsService));
- // 泛型注册
- services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
- // 委托工厂
- services.AddTransient<IService>(sp =>
- new Service(sp.GetRequiredService<IOtherService>()));
复制代码 三、注入方式大全
1. 构造函数注入(最保举)
- public class ProductController
- {
- private readonly IProductService _service;
-
- public ProductController(IProductService service)
- {
- _service = service; // 由DI容器自动注入
- }
- }
复制代码 2. 方法注入
- public class ReportGenerator
- {
- public void Generate(IReportFormatter formatter)
- {
- // 使用方法参数注入
- }
- }
复制代码 3. 属性注入(不保举但某些场景必要,如blazor)
- public class NotificationService
- {
- [Inject] // 需要特定属性标记
- public ILogger Logger { get; set; }
- }
复制代码 4. 从容器直接剖析(应避免,但有时必要)
- var service = serviceProvider.GetRequiredService<IMyService>();
复制代码 四、实际应用场景
1. 分层架构中的DI
- // 基础设施层
- services.AddDbContext<AppDbContext>(options =>
- options.UseSqlServer(Configuration.GetConnectionString("Default")));
- // 应用层
- services.AddScoped<IOrderService, OrderService>();
- // 领域层
- services.AddTransient<IDomainEventDispatcher, DomainEventDispatcher>();
- // 表现层
- services.AddControllersWithViews();
复制代码 2. 选项模式(Options Pattern)
- // 注册配置
- services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
- // 注入使用
- public class EmailService
- {
- private readonly EmailSettings _settings;
-
- public EmailService(IOptions<EmailSettings> options)
- {
- _settings = options.Value;
- }
- }
复制代码 3. 日记集成
- public class ProductService
- {
- private readonly ILogger<ProductService> _logger;
-
- public ProductService(ILogger<ProductService> logger)
- {
- _logger = logger; // 自动注入日志系统
- }
- }
复制代码 五、高级主题
1. 第三方容器集成
- // Autofac示例
- builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
- .ConfigureContainer<ContainerBuilder>(builder =>
- {
- builder.RegisterModule(new MyAutofacModule());
- });
复制代码 2. 装饰器模式
- // 原始服务
- services.AddScoped<IDataService, DataService>();
- // 装饰器
- services.Decorate<IDataService, CachingDataService>();
复制代码 3. 验证服务注册
- // 检查所有服务是否已注册
- var provider = services.BuildServiceProvider();
- foreach (var service in services)
- {
- provider.GetRequiredService(service.ServiceType); // 会抛出异常如果未注册
- }
复制代码 六、最佳实践
- 构造函数保持简朴:只注入必要的依赖
- 避免服务定位器模式:不要滥用GetService
- 注意生命周期:避免Scoped服务被Singleton服务引用
- 使用接口:尽量依赖抽象而非具体实现
- 避免过分注入:如一个类注入超过5个服务,考虑重构
七、常见题目解决
循环依赖题目
- // 错误示例
- class A { public A(B b) {} }
- class B { public B(A a) {} }
- // 解决方案:
- // 1. 重构设计,提取公共逻辑到第三个类
- // 2. 使用属性注入或方法注入替代构造函数注入
复制代码 多实现选择
- // 注册多个实现
- services.AddTransient<IMessageService, EmailService>();
- services.AddKeyedTransient<IMessageService, SmsService>("SMS");
- // 解析所有实现
- var services = provider.GetServices<IMessageService>();
- // 命名解析
- var smsService = provider.GetRequiredKeyedService<IMessageService>("SMS");
复制代码 感谢各位大佬的观看!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|