You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quartz.NET 3.0.3与Simple Injector构造函数注入实现方法

嘿,我刚好处理过类似的场景,Quartz.Net v3.x和Simple Injector的构造注入确实不能直接用默认的JobFactory,得自定义一个来衔接两者,给你一套可行的方案:

1. 实现Quartz自定义JobFactory

Quartz默认会自己实例化Job对象,所以我们需要替换成Simple Injector来创建实例,这样才能触发构造函数注入。创建一个实现IJobFactory的类:

using Quartz;
using SimpleInjector;
using System;

public class SimpleInjectorJobFactory : IJobFactory
{
    private readonly Container _container;

    public SimpleInjectorJobFactory(Container container)
    {
        _container = container ?? throw new ArgumentNullException(nameof(container));
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        // 为Job创建执行上下文Scope(如果Job依赖Scoped服务,比如DbContext,这一步很关键)
        var scope = _container.BeginExecutionContextScope();
        try
        {
            // 让Simple Injector解析Job实例
            var job = (IJob)scope.GetInstance(bundle.JobDetail.JobType);
            
            // 将Scope与Job绑定,方便后续释放
            if (job is IScopedJob scopedJob)
            {
                scopedJob.Scope = scope;
            }
            
            return job;
        }
        catch
        {
            // 解析失败时释放Scope
            scope.Dispose();
            throw;
        }
    }

    public void ReturnJob(IJob job)
    {
        // 释放Scope和Job资源
        if (job is IScopedJob scopedJob)
        {
            scopedJob.Scope.Dispose();
        }
        else if (job is IDisposable disposableJob)
        {
            disposableJob.Dispose();
        }
    }
}

// 定义接口关联Job和Scope
public interface IScopedJob : IJob, IDisposable
{
    Scope Scope { get; set; }
}
2. 注册Job和依赖到Simple Injector

不要直接注册IJob到JobWorker,而是注册具体的Job类(因为Quartz会根据具体类型请求实例),同时确保依赖项(比如日志)已正确注册:

var container = new Container();

// 注册日志依赖(替换成你实际的日志框架注册方式)
container.Register<ILogger>(() => new LoggerImplementation(), Lifestyle.Singleton);

// 注册你的JobWorker,生命周期按需选择Transient/Scoped
container.Register<JobWorker>(Lifestyle.Transient);

// 验证容器配置(提前发现注册问题)
container.Verify();
3. 配置Quartz Scheduler使用自定义JobFactory

在创建Quartz调度器时,把我们的SimpleInjectorJobFactory设置进去:

using Quartz;
using Quartz.Impl;
using System.Threading.Tasks;

// 初始化Quartz调度器工厂
var schedulerFactory = new StdSchedulerFactory();
var scheduler = await schedulerFactory.GetScheduler();

// 绑定自定义JobFactory
scheduler.JobFactory = new SimpleInjectorJobFactory(container);

// 定义Job和Trigger
var jobDetail = JobBuilder.Create<JobWorker>()
    .WithIdentity("JobWorker", "DefaultGroup")
    .Build();

var trigger = TriggerBuilder.Create()
    .WithIdentity("JobWorkerTrigger", "DefaultGroup")
    .StartNow()
    .WithSimpleSchedule(x => x.WithIntervalInSeconds(10).RepeatForever())
    .Build();

// 将Job和Trigger添加到调度器
await scheduler.ScheduleJob(jobDetail, trigger);

// 启动调度器
await scheduler.Start();
4. 改造你的JobWorker实现

让JobWorker实现IScopedJob接口,接收Scope并正确释放资源,同时在构造函数中注入依赖:

public class JobWorker : IScopedJob
{
    private readonly ILogger _logger;
    public Scope Scope { get; set; }

    // 构造函数注入日志依赖
    public JobWorker(ILogger logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("JobWorker执行于:{Time}", DateTime.Now);
        // 这里编写你的Job业务逻辑
        await Task.CompletedTask;
    }

    public void Dispose()
    {
        // 释放Scope,同时释放Scope内的所有Scoped依赖
        Scope?.Dispose();
    }
}
关键注意点
  • 不要用Container.Register<IJob, JobWorker>():Quartz创建Job时基于具体类型请求实例,直接注册具体类型才能让Simple Injector正确解析。
  • Scope的处理:如果Job依赖Scoped生命周期服务(比如数据库上下文),一定要用BeginExecutionContextScope创建Scope,避免依赖实例无法释放或重复使用。
  • 容器验证:调用container.Verify()能提前发现注册错误,避免运行时才暴露问题。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 06:57:49