共享同一接口的抽象类依赖注入:ServiceBA注入为空的解决方法
依赖注入中ServiceBA注入为null的解决方法
问题背景
类层级结构
public abstract class ServiceBase<T> : IServiceBase protected ServiceBase(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) public abstract class ServiceA<T> : ServiceBase<T> protected ServiceA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) public abstract class ServiceAA : ServiceA<Type1> protected ServiceAA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) public abstract class ServiceAB : ServiceA<Type2> protected ServiceAB(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) public abstract class ServiceB<T> : ServiceBase<Type3> protected ServiceB(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) public abstract class ServiceBA : ServiceB<Type1> protected ServiceBA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) public abstract class ServiceBB : ServiceB<Type2> protected ServiceBB(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3)
现有依赖注入配置
... builder.Services.AddScoped<IExtService1, extService1>(); builder.Services.AddScoped<IExtService2, extService2>(); builder.Services.AddScoped<IExtService3, extService3>(); builder.Services.AddScoped<IServiceBase, ServiceAA>(); builder.Services.AddScoped<IServiceBase, ServiceAB>(); builder.Services.AddScoped<IServiceBase, ServiceBA>(); builder.Services.AddScoped<IServiceBase, ServiceBB>(); ...
需求与问题
想要在ServiceA<T>中注入ServiceBA,修改后的构造函数如下:
public abstract class ServiceA<T> : ServiceBase<T> protected ServiceA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3, ServiceBA<T> serviceBA) : base(extService1, extService2, extService3)
但注入后的serviceBA始终为null,需要解决这个问题。
问题原因与解决步骤
1. 核心问题:类型不匹配
首先看ServiceBA的定义:它是ServiceB<Type1>的抽象子类,没有泛型参数T,你试图注入ServiceBA<T>,但这个类型根本不存在,DI容器找不到匹配的服务,自然返回null。
2. 解决思路:调整类结构与DI配置
根据你的需求(ServiceA<Type1>对应ServiceBA,ServiceA<Type2>对应ServiceBB),提供两种可行方案:
方案一:将ServiceB子类改为泛型
把ServiceBA和ServiceBB改成泛型类,匹配ServiceA的T参数,同时提供具体实现类(DI无法实例化抽象类):
// 泛型抽象类 public abstract class ServiceBA<T> : ServiceB<T> { protected ServiceBA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) { } } // Type1对应的具体实现 public class ServiceBAImpl : ServiceBA<Type1> { public ServiceBAImpl(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) { } } // 同理改造ServiceBB<T>和ServiceBBImpl
然后更新DI注册:
builder.Services.AddScoped(typeof(ServiceBA<>), typeof(ServiceBAImpl<>)); builder.Services.AddScoped(typeof(ServiceBB<>), typeof(ServiceBBImpl<>));
最后修正ServiceA<T>的构造函数:
public abstract class ServiceA<T> : ServiceBase<T> { protected ServiceA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3, ServiceBA<T> serviceBA) : base(extService1, extService2, extService3) { // 这里serviceBA就能正常注入了 } }
方案二:为ServiceB子类定义专用接口
如果不需要泛型,给ServiceBA和ServiceBB分别定义专属接口,让DI能精准匹配:
// 定义专用接口 public interface IServiceBA : IServiceBase { } public interface IServiceBB : IServiceBase { } // 修改ServiceBA和ServiceBB实现对应接口 public abstract class ServiceBA : ServiceB<Type1>, IServiceBA { protected ServiceBA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) { } } public abstract class ServiceBB : ServiceB<Type2>, IServiceBB { protected ServiceBB(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3) : base(extService1, extService2, extService3) { } } // 提供具体实现类 public class ServiceBAImpl : ServiceBA { /* 构造函数继承 */ } public class ServiceBBImpl : ServiceBB { /* 构造函数继承 */ }
更新DI注册:
builder.Services.AddScoped<IServiceBA, ServiceBAImpl>(); builder.Services.AddScoped<IServiceBB, ServiceBBImpl>();
这种方案下,需要在ServiceAA和ServiceAB中分别注入对应的接口(因为ServiceA<T>无法直接区分T对应的服务):
// ServiceAA中注入IServiceBA public abstract class ServiceAA : ServiceA<Type1> { protected ServiceAA(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3, IServiceBA serviceBA) : base(extService1, extService2, extService3) { } } // ServiceAB中注入IServiceBB public abstract class ServiceAB : ServiceA<Type2> { protected ServiceAB(IExtService1 extService1, IExtService2 extService2, IExtService3 extService3, IServiceBB serviceBB) : base(extService1, extService2, extService3) { } }
3. 关键注意点
- 抽象类无法被DI直接实例化:所有抽象类(
ServiceAA、ServiceAB、ServiceBA等)都必须有对应的具体实现类,DI容器只能创建具体类的实例。 - 避免依赖混乱:不要直接注入具体类,优先使用接口,这样能降低耦合度,也方便DI容器管理。
内容的提问来源于stack exchange,提问作者Xav Sc
相关产品推荐
相关产品推荐

