ASP.NET Core Worker Service依赖注入异常:IGenericRepository<Configuration>服务未注册
这种DI容器找不到已注册服务的问题我之前踩过好几次坑,特别容易因为一些细节疏忽导致。咱们一步步来排查可能的原因,总能找到问题所在:
1. 先确认服务注册代码真的被执行到了
Worker Service的Program.cs通常是用Host.CreateDefaultBuilder构建宿主的,你要确保服务注册代码写在ConfigureServices委托里,而且没有被条件分支(比如if判断)跳过。比如:
var host = Host.CreateDefaultBuilder(args) .ConfigureServices((context, services) => { // 确保你的服务注册在这里,且这段代码一定会执行 services.AddScoped<IGenericRepository<Configuration>, GenericRepository<Configuration>>(); services.AddHostedService<Worker>(); }) .Build(); host.Run();
如果注册代码写在宿主构建完成之后,DI容器肯定不会识别到。
2. 最常见的坑:命名空间不匹配
错误提示里的接口完全限定名是Cavipetrol.Domain.Interface.Repositories.IGenericRepository1[Cavipetrol.Domain.Entities.Configuration]`,你要100%确认以下几个点:
- Program.cs里注册时用的
IGenericRepository<Configuration>,和Worker里获取服务时用的是同一个命名空间的类型?- 右键Program.cs里的
IGenericRepository选择「转到定义」,查看命名空间是否为Cavipetrol.Domain.Interface.Repositories; - 再到Worker里右键
IGenericRepository<Configuration>转到定义,对比命名空间是否完全一致。
- 右键Program.cs里的
- 同理,
Configuration类在注册和Worker里的引用是不是同一个命名空间的?有没有可能Worker里不小心引用了另一个项目/文件夹下的同名Configuration类?
哪怕类型名一模一样,只要命名空间不同,DI容器就会认为是两个完全不同的类型,自然找不到注册的服务。
3. 检查实现类是否正确匹配接口
你要确认GenericRepository<Configuration>确实正确实现了IGenericRepository<Configuration>的所有方法:
- 检查实现类的方法签名是否和接口完全一致:比如接口里的
Task<IEnumerable<T>> GetAllAsync(),实现类是不是返回Task<IEnumerable<Configuration>>,有没有遗漏async、返回类型不对的情况? - 检查泛型约束:接口里的
where T : class,实现类GenericRepository<T>是不是也有同样的约束?如果实现类的约束更严格,DI容器可能不认可它是接口的实现。
可以在Program.cs里写一行测试代码,看编译器会不会报错:
// 如果这行代码编译报错,说明实现类和接口不匹配 IGenericRepository<Configuration> test = new GenericRepository<Configuration>();
如果编译报错,那就是实现类的问题,得先修复实现逻辑。
4. 确认作用域创建是否正确
在Worker的ExecuteAsync方法里,你是不是正确创建了作用域?比如:
// 正确的作用域创建方式 using var scope = _serviceProvider.CreateScope(); var configurationRepository = scope.ServiceProvider.GetRequiredService<IGenericRepository<Configuration>>();
如果scope不是通过_serviceProvider.CreateScope()创建的,或者_serviceProvider本身是根服务提供者(而非注入的IServiceProvider),可能会导致作用域内的服务无法被解析。
5. 启动时提前验证依赖
可以在Program.cs里添加依赖验证代码,这样程序启动时就会立即检查服务是否能被解析,不用等到Worker执行才报错,更容易排查:
var host = builder.Build(); // 验证服务依赖 using var scope = host.Services.CreateScope(); var services = scope.ServiceProvider; try { // 尝试解析目标服务 var repo = services.GetRequiredService<IGenericRepository<Configuration>>(); Console.WriteLine("服务解析成功!"); } catch (Exception ex) { var logger = services.GetRequiredService<ILogger<Program>>(); logger.LogCritical(ex, "启动时验证服务依赖失败"); throw; } host.Run();
我之前碰到过最多次的情况就是命名空间不匹配——比如项目重构后,某个文件的命名空间没改,导致注册和使用的是两个不同的IGenericRepository类型,仔细核对命名空间通常就能解决。
备注:内容来源于stack exchange,提问作者Nico Florez

