问题描述
我正在尝试在Windows服务中使用Quartz.Net v3.0.3和Simple Injector。
I am trying to use Quartz.Net v3.0.3 and Simple Injector in a windows service.
我有一个工作类别,在这个类别下我想注入一些
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"));
}
}
我尝试注册容器。在我的DI层上注册< IJob,JobWorker>();
,但这无济于事。
I tried registering Container.Register<IJob, JobWorker>();
on my DI layer but this doesn't help.
如果我删除了注入的依赖项并简单地使用默认的无参数构造函数可以正确执行作业。
If i remove the injected dependency and simply use the default parameterless constructor the job fires correct.
根据Steven的以下帖子,建议创建一个Factory,但是提供的答案已过时新框架的上下文,我完全迷失了如何将依赖注入到作业中。
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.
推荐答案
@Rabban提供的链接仍然有效,使用 IServiceProvider
是一个不错的设计选择,但是您可以使用任何想要的具体容器。
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.
这是我根据拉邦的回答使用<$ c $得出的2分c>石英3.0.4 和 SimpleInjector 4.2.1
:
Here are my 2c based on Rabban's answer using Quartz 3.0.4
and SimpleInjector 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 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.
我建议为每个作业创建一个接口,而不要为此使用 Quartz IJob
。
I suggest creating an Interface for each Job and not using Quartz IJob
for that.
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上使用断点了。
干杯。
Now you can use a breakpoint on Execute.Cheers.
编辑
PS:史蒂文的答案非常好,我认为您可以使用它来将上下文更新为您的上下文。
现在很严重,欢呼。
P.S.: Steven answer is very good and I think you can play with it to update that context to yours.Now serious, cheers.
这篇关于Quartz.NET 3.0.3和简单注入器的构造方法注入方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!