简体   繁体   English

使用 Quartz.NET 3.0.3 和简单注入器如何进行构造函数注入

[英]Constructor injection with Quartz.NET 3.0.3 and Simple Injector How To

I am trying to use Quartz.Net v3.0.3 and Simple Injector in a windows service.我正在尝试在 Windows 服务中使用 Quartz.Net v3.0.3 和 Simple Injector。

I have a job class below which i would like to inject some dependencies such as my logger into.我在下面有一个作业类,我想在其中注入一些依赖项,例如我的记录器。

public class JobWorker :  IJob
{
    private ILogger _logger;

    public JobWorker(ILogger logger)
    {
        _logger = logger;
    }

    public Task Execute(IJobExecutionContext context)
    {
        return Task.Run(() =>_logger.Log("Do Work"));
    }
}

I tried registering Container.Register<IJob, JobWorker>();我尝试注册Container.Register<IJob, JobWorker>(); on my DI layer but this doesn't help.在我的 DI 层上,但这没有帮助。

If i remove the injected dependency and simply use the default parameterless constructor the job fires correct.如果我删除注入的依赖项并简单地使用默认的无参数构造函数,作业就会正确触发。

Accord to the post below by Steven, the suggestion is to create a Factory, however the answer provided is out of date in context of the new framework and i'm completely lost as how to inject dependencies into jobs.根据史蒂文下面的帖子,建议是创建一个工厂,但是提供的答案在新框架的上下文中已经过时,我完全不知道如何将依赖项注入作业。

Constructor injection with Quartz.NET and Simple Injector 使用 Quartz.NET 和 Simple Injector 进行构造函数注入

The link provided by @Rabban is still valid and using IServiceProvider is a good design choice, but you can use whatever concrete Container you want. @Rabban 提供的链接仍然有效,使用IServiceProvider是一个不错的设计选择,但您可以使用任何您想要的具体容器。

Here are my 2c based on Rabban's answer using Quartz 3.0.4 and SimpleInjector 4.2.1 :这是我的 2c 基于 Rabban 使用Quartz 3.0.4SimpleInjector 4.2.1的回答:

using NLog;
using Quartz;
using Quartz.Spi;
using System;

namespace My.Dear.App.Infrastructure
{

    public class SomeJobFactory : IJobFactory
    {
        private static ILogger logger = LogManager.GetCurrentClassLogger();
        private readonly IServiceProvider serviceProvider;

        public DexJobFactory(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            try
            {
                IJobDetail jobDetail = bundle.JobDetail;
                Type jobType = jobDetail.JobType;
                logger.Debug($"Producing instance of Job '{jobDetail.Key}', class={jobType.FullName}");

                return serviceProvider.GetService(jobType) as IJob;
            }
            catch (Exception ex)
            {
                logger.Error(ex, Constants.ErrorAt, nameof(IJobFactory.NewJob));
                throw new SchedulerException($"Problem instantiating class '{bundle.JobDetail.JobType.FullName}'", ex);
            }
        }

        public void ReturnJob(IJob job)
        {
            var disposable = job as IDisposable;
            disposable?.Dispose();
        }
    }
}

Works like a charm for me.对我来说就像一个魅力。

How to get an instance?如何获取实例?

public static async Task RegisterQuartz(Container container)
{
    ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
    IScheduler scheduler = await schedulerFactory.GetScheduler();
    IJobFactory jobFactory = new SomeJobFactory(container);
    scheduler.JobFactory = jobFactory;

    container.RegisterInstance(schedulerFactory);
    container.RegisterInstance(jobFactory);
    container.RegisterInstance(scheduler);
    container.Register<IDearJob, DearJob>();
}

Oh, and don't forget to register your Jobs.哦,别忘了注册您的工作。 Otherwise it may not work.否则它可能无法工作。

I suggest creating an Interface for each Job and not using Quartz IJob for that.我建议为每个作业创建一个接口,而不是为此使用Quartz IJob

public interface IDearJob : IJob { }

public interface DearJob : IDearJob 
{
    private readonly ISomeService service;

    public DearJob(ISomeService service)
    {
        this.service = service;
    }

    public async Task Execute(IJobExecutionContext context) 
    {
        // retrieve context if you need
        await this.service.DoSomethingAsync(/*params*/);
    }
}

Now you can use a breakpoint on Execute.现在您可以在 Execute 上使用断点。 Cheers.干杯。

EDIT编辑

PS: Steven answer is very good and I think you can play with it to update that context to yours. PS:史蒂文的回答非常好,我认为您可以使用它来更新您的上下文。 Now serious, cheers.现在认真,干杯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM