You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Quartz.NET:如何通过.NET依赖注入为带非空构造函数的作业注入依赖

解决Quartz.NET中依赖注入作业的实例化问题

看起来你遇到的核心问题是调度器没有正确关联你配置的Microsoft DI作业工厂,导致它仍在尝试用默认逻辑(无参构造函数)实例化你的作业。结合Quartz 3.2.4的特性,我来一步步帮你修正:

1. 修正核心配置逻辑

你的Quartz配置已经接近正确,但有几个关键细节需要调整:

正确的DI注册步骤

Program.cs(或Startup.cs)中,按以下方式配置Quartz服务:

// 注册Quartz并配置DI作业工厂
services.AddQuartz(q =>
{
    // 启用Microsoft DI作用域作业工厂(这是让作业从DI容器获取实例的关键)
    q.UseMicrosoftDependencyInjectionScopedJobFactory();

    // 注册作业到Quartz系统(同时会自动关联DI容器)
    var jobKey = new JobKey("MyID", "MyGroup");
    q.AddJob<MyJob>(opts => opts.WithIdentity(jobKey));

    // 配置触发器并绑定到目标作业
    q.AddTrigger(opts => opts
        .ForJob(jobKey)
        .WithIdentity("MyTriggerID") // 建议触发器ID与作业区分开,避免冲突
        .StartNow()
        .WithCronSchedule("*/1 * * * * ?")); // 每秒执行一次
});

// 添加Quartz托管服务,让调度器在后台自动启动并管理生命周期
services.AddQuartzHostedService(options =>
{
    // 应用关闭时等待正在执行的作业完成
    options.WaitForJobsToComplete = true;
});

// 显式注册作业到DI容器(可选,但确保Scoped生命周期的作业能被正确解析)
services.AddScoped<MyJob>();

为什么之前的配置失效?

你之前手动创建JobDetailTrigger并调用_scheduler.ScheduleJob,但如果调度器实例不是通过DI容器获取的(而是手动构建的),它不会自动关联你配置的MicrosoftDependencyInjectionScopedJobFactory。使用AddQuartzHostedService会让DI自动管理调度器的创建与配置,确保作业工厂被正确应用。

2. 修正作业类的小问题

你的Execute方法缺少返回值,会导致编译错误,需要补充返回Task.CompletedTask

public class MyJob : IJob
{
    private readonly ILogger<MyJob> _logger;

    public MyJob(ILogger<MyJob> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public Task Execute(IJobExecutionContext context)
    {
        _logger.LogDebug("It's working!");
        return Task.CompletedTask; // 必须返回已完成的Task
    }
}

3. 验证包版本一致性

确保你安装的QuartzQuartz.Extensions.DependencyInjection版本完全一致(都是3.2.4),版本不匹配很容易导致DI集成失效。你可以在NuGet包管理器中检查,或者查看.csproj文件:

<PackageReference Include="Quartz" Version="3.2.4" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.2.4" />

4. 避免手动创建调度器(重要)

如果你之前是自己手动实例化IScheduler,请停止这种做法!通过AddQuartzHostedService,DI会自动为你创建并初始化调度器,且自动应用配置的作业工厂。

如果确实需要手动操作调度器,应通过DI注入ISchedulerFactory来获取实例:

public class SomeService
{
    private readonly ISchedulerFactory _schedulerFactory;

    public SomeService(ISchedulerFactory schedulerFactory)
    {
        _schedulerFactory = schedulerFactory;
    }

    public async Task ScheduleJobManually()
    {
        var scheduler = await _schedulerFactory.GetScheduler();
        // 此处的调度器已绑定配置的DI作业工厂
        // 可继续添加作业/触发器,但推荐优先在AddQuartz中配置
    }
}

按照以上步骤调整后,你的作业就能正确从DI容器获取ILogger<MyJob>实例,不再抛出无参构造函数的错误。

内容的提问来源于stack exchange,提问作者Wouter Vandenputte

火山引擎 最新活动