【问题标题】:Scheduling a Quartz.net Job with dependency-injection使用依赖注入调度 Quartz.net 作业
【发布时间】:2021-09-23 02:26:13
【问题描述】:

我正在使用 EF Core 开发我的第一个项目,并使用 DB Context 进行依赖注入。但是我遇到了一个问题,因为 Quartz.net 3 似乎不允许 ImportJob 类上的任何参数。所以我的 DI 方法在这种情况下不起作用。我知道我想要一个新的上下文,因为这将在后台运行,是否有不同的方法来创建数据库上下文以便我可以执行此任务?

public class ImportJob : IJob
{
    private readonly SContext _db;

    //Quartz.net doesn't appear to like that I'm injecting these, 
    //because if I remove this parameter, execute...executes.
    public ImportJob(SContext db)
    {
        _db = db;
    }

    public Task Execute(IJobExecutionContext context)
    {
        var cc = new CC(_db);
        return Task.CompletedTask;
    }
}

【问题讨论】:

    标签: c# dependency-injection quartz-scheduler


    【解决方案1】:

    一种方法是使用StdSchedulerFactory,这是一个实现IJobFactory并采用IServiceProvider的作业工厂

    示例

    public class JobFactory : IJobFactory
    {
       private readonly IServiceProvider _serviceProvider;
    
       public JobFactory(IServiceProvider serviceProvider)
          => _serviceProvider = serviceProvider;
    
       public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
       {
          try
          {
             var jobDetail = bundle.JobDetail;
             var jobType = jobDetail.JobType;
             return _serviceProvider.GetService(jobType) as IJob;
          }
          catch (Exception ex)
          {
    
             throw new SchedulerException($"Problem instantiating class '{bundle.JobDetail.JobType.FullName}'", ex);
          }
       }
    
       public void ReturnJob(IJob job)
          => (job as IDisposable)?.Dispose();
    }
    

    根据您的 DI 框架,注册看起来有点像这样

    // register, your container as an IServiceProvider
    container.RegisterInstance<IServiceProvider>(container);
    
    // create the scheduler
    var scheduler = await StdSchedulerFactory.GetDefaultScheduler(cancellationTokenSource.Token);
    
    // add your factory to the scheduler
    scheduler.JobFactory = new JobFactory(container);
    
    // register the scheduler
    container.RegisterInstance(scheduler);
    
    // register your jobs
    
    container.Collection.Register<IJob>(GetType().Assembly);
    

    那么你的工作可以是这样的

    public class ImportJob : IJob
    {
        private readonly SContext _db;
    
        //Quartz.net doesn't appear to like that I'm injecting these, 
        //because if I remove this parameter, execute...executes.
        public ImportJob(SContext db)
        {
            _db = db;
        }
    
        public Task Execute(IJobExecutionContext context)
        {
            var cc = new CC(_db);
            return Task.CompletedTask;
        }
    }
    

    注意:这是一个基本的想法,不是一个完整的例子,很大程度上取决于你自己的设置和框架

    简而言之,当 Quartz 创建一个 job 时,它会使用您的 Factory 和 container 来启动允许注入的工作。

    【讨论】:

    • 我是 DI 和 EF Core 的新手,在您的示例中我看不到我的 _db 在哪里?
    • @JoeStellato 这是 DI / Quartz 问题,不是工作问题。它的作用是让你的工作支持 DI。它通过使用您自己的作业工厂和容器来启动作业和 DI 来实现这一点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多