如何通过依赖注入在嵌套类链的底层类中获取所需服务?
解决方案
最优方案:使用依赖注入(DI)容器托管所有实例
构造函数参数膨胀问题的根源是手动通过new关键字创建实例,把实例化控制权交给DI容器即可从根源解决该问题,无需在A、B中传递任何不需要的服务参数。
实现步骤
- 调整A、B、C的构造函数,仅注入自身直接依赖的对象:
public class A { private readonly B _classB; // 仅注入直接依赖的B,不需要感知ILogger public A(B classB) { _classB = classB; } } public class B { private readonly C _classC; // 仅注入直接依赖的C,不需要感知ILogger public B(C classC) { _classC = classC; } } public class C { private readonly ILogger<C> _logger; // 仅注入自身需要的ILogger public C(ILogger<C> logger) { _logger = logger; } }
- 在DI容器中注册所有类型,以ASP.NET Core为例:
// Program.cs 中注册 builder.Services.AddTransient<A>(); builder.Services.AddTransient<B>(); builder.Services.AddTransient<C>(); // ILogger 是框架默认注册的,无需手动注册
- 后续需要使用A时,直接从容器中获取A的实例即可,容器会自动按A→B→C的依赖链完成所有实例的创建和依赖注入,全程不需要手动传参,A、B完全感知不到ILogger的存在。
兼容方案:服务定位器模式(不推荐,仅作为无法调整上层实例化逻辑时的兜底方案)
如果A、B的代码无法修改,必须保留手动new的逻辑,可以通过全局服务定位器获取ILogger实例:
public class C { private readonly ILogger<C> _logger; public C() { // 从全局服务提供者获取实例,AppContext.ServiceProvider需要提前配置为全局DI容器实例 _logger = AppContext.ServiceProvider.GetRequiredService<ILogger<C>>(); } }
注意:该模式属于依赖注入反模式,会隐藏类的真实依赖,提升单元测试的难度,仅在迫不得已的场景下使用。
内容的提问来源于stack exchange,提问作者Антон Юдин
相关产品推荐
相关产品推荐

