C# Worker进程中如何通过依赖注入正确使用Scoped服务
问题原因
错误本质是.NET依赖注入的生命周期限制:AddHostedService 注册的 BackgroundService 派生类默认是单例生命周期,而你将 IVMValidationManager 注册为了范围(Scoped)生命周期。DI容器不允许单例服务直接注入范围服务,避免范围服务被意外提升为单例、造成生命周期混乱,所以直接抛出了这个校验错误。
解决方案
方案1:调整服务生命周期(最简单,适用于无状态/不需要范围隔离的场景)
如果你的 VMValidationManager 不需要每次调用都创建新实例、也没有依赖其他范围服务,直接修改Program.cs中的服务注册代码,把AddScoped改成AddSingleton即可:
.ConfigureServices((hostContext, services) => { // 将Scoped生命周期调整为Singleton services.AddSingleton<IVMValidationManager, VMValidationManager>(); services.AddHostedService<Worker>(); });
方案2:手动创建范围获取服务(适用于确实需要Scoped生命周期的场景)
如果你的 IVMValidationManager 本身依赖其他Scoped服务、或者确实需要每次调用时使用新的实例,就不要直接在构造函数注入IVMValidationManager,改为注入IServiceProvider,每次使用前手动创建服务范围,从范围内解析服务:
修改Worker类代码如下:
public class Worker : BackgroundService { private readonly IServiceProvider _serviceProvider; public Worker(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // 手动创建服务范围 using var scope = _serviceProvider.CreateScope(); // 从当前范围解析IVMValidationManager var vmValidationManager = scope.ServiceProvider.GetRequiredService<IVMValidationManager>(); vmValidationManager.RunVMValidationScripts(); } }
注意:如果你的Worker是循环执行定时任务的场景,建议把创建范围的逻辑放到每次任务执行的代码块内,保证每次执行都使用新的Scoped服务实例。范围会在
using代码块结束后自动释放,范围内解析的所有Scoped服务也会跟着被回收,符合生命周期规范。
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

