@Rabban 提供的链接仍然有效,使用IServiceProvider 是一个不错的设计选择,但您可以使用任何您想要的具体 Container。
这是我的 2c,基于 Rabban 使用 Quartz 3.0.4 和 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>();
}
哦,别忘了注册您的职位。否则可能无法正常工作。
我建议为每个作业创建一个接口,而不是为此使用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*/);
}
}
现在您可以在执行时使用断点。
干杯。
编辑
P.S.:Steven 的回答非常好,我认为您可以使用它来更新您的上下文。
现在是认真的,干杯。