Quartz.NET自定义Job配置DI能力注册及DI异常解决
问题解决方案
1. 过时的UseMicrosoftDependencyInjectionJobFactory替代方案
新版Quartz中,UseMicrosoftDependencyInjectionJobFactory已被废弃,替代方案是使用UseMicrosoftDependencyInjectionScopedJobFactory,它支持更合理的作用域管理,确保Job执行时能正确获取作用域服务。修改后的注册代码如下:
public static class QuartzExtensions { public static IServiceCollection AddQuartzSetup(this IServiceCollection services) { services.AddQuartz(opts => { // 替代过时方法,启用依赖注入作用域Job工厂 opts.UseMicrosoftDependencyInjectionScopedJobFactory(); }); services.AddQuartzHostedService(options => { options.WaitForJobsToComplete = true; }); // 注册异步配置类 services.AddTransient<IAsyncConfigureOptions<QuartzOptions>, UpdateS3BackgroundJobSetup>(); return services; } }
如果使用较新版本的Quartz.AspNetCore,AddQuartz默认已集成DI Job工厂支持,也可省略显式调用UseMicrosoftDependencyInjectionScopedJobFactory,但显式声明会更清晰。
2. 解决单例IOptions<QuartzOptions>消费作用域服务的DI异常
问题根源
IConfigureOptions<QuartzOptions>实例是单例生命周期,而IApplicationConfigurationDbContext是作用域生命周期,根据.NET DI规则,单例服务不能直接依赖作用域服务,否则会导致作用域服务被单例持有,引发生命周期不匹配异常。
解决方法
改用IAsyncConfigureOptions<QuartzOptions>异步配置接口,通过IServiceScopeFactory手动创建作用域获取DbContext,避免直接注入作用域服务到单例中。修改配置类如下:
public class UpdateS3BackgroundJobSetup : IAsyncConfigureOptions<QuartzOptions> { private readonly IServiceScopeFactory _scopeFactory; public UpdateS3BackgroundJobSetup(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } public async Task ConfigureAsync(QuartzOptions options, CancellationToken cancellationToken) { // 创建临时作用域,获取DbContext using var scope = _scopeFactory.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<IApplicationConfigurationDbContext>(); var configuration = await dbContext.ApplicationConfigurations .Where(cfg => cfg.Name == "metamorph-db") .FirstOrDefaultAsync(cancellationToken); var jobKey = JobKey.Create(nameof(OutgoingRegistriesJob)); options .AddJob<OutgoingRegistriesJob>(jobBuilder => jobBuilder.WithIdentity(jobKey)) .AddTrigger(trigger => trigger .ForJob(jobKey) .WithSimpleSchedule(schedule => schedule.WithIntervalInMinutes(5).RepeatForever())); } }
额外注意事项
- 替换原注册方式:将
services.ConfigureOptions<UpdateS3BackgroundJobSetup>()改为services.AddTransient<IAsyncConfigureOptions<QuartzOptions>, UpdateS3BackgroundJobSetup>(),适配异步配置接口。 - 移除
async void:原代码中Configure方法使用async void会导致异步操作无法被正确追踪,改用IAsyncConfigureOptions的ConfigureAsync方法(返回Task),确保异步操作可靠性。
内容的提问来源于stack exchange,提问作者hackp0int
相关产品推荐
相关产品推荐

