使用Quartz.NET 3.0.3和Simple Injector的构造函数注入如何

时间:2018-03-01 20:05:39

标签: c# dependency-injection windows-services quartz.net simple-injector

我正在尝试在Windows服务中使用Quartz.Net v3.0.3和Simple Injector。

我有一个工作类,我想在其中注入一些依赖项,例如我的记录器。

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"));
    }
}

我尝试在我的DI层注册Container.Register<IJob, JobWorker>();,但这没有帮助。

如果我删除了注入的依赖项,只需使用默认的无参数构造函数,则该作业将触发正确。

根据Steven的下面的帖子,建议是创建一个工厂,但是在新框架的背景下提供的答案是过时的,并且我完全失去了如何将依赖关系注入到工作中。 / p>

Constructor injection with Quartz.NET and Simple Injector

1 个答案:

答案 0 :(得分:2)

@Rabban提供的链接仍然有效,使用IServiceProvider是一个很好的设计选择,但你可以使用你想要的任何具体容器。

以下是我的5c基于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();
        }
    }
}

对我来说就像是一种魅力。

如何获取实例?

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

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

哦,别忘了注册你的工作。否则可能无效。

我建议为每个作业创建一个界面,而不是使用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*/);
    }
}

现在您可以在Execute上使用断点。 欢呼声。

修改

P.S。:史蒂文的回答非常好,我认为你可以用它来更新你的背景。 现在认真,欢呼。