有一天,小明来问我这个问题:
如何使用Dotnet Core DI注入Quartz Job所需的依赖物件?
首先,我们创建一个Quartz Job对象,一个简单的Quartz Job示例代码如下:
public class MyJob : IJob { public MyJob(IMyLogger logger) { //Blah... } void Execute(JobExecutionContext context) { //Blah... }}
通常我们是按照下面方式开始建立Quartz Job,
var job = JobBuilder.Create<MyJob>() .WithIdentity("myJob") .Build();
但是上面的程式码没办法从Dotnet Core DI 自动注入, 幸运的是Quartz 提供了IJobFactory 介面接口, 它允许我们创建自定义的JobFactory 类别.
现在我们创建一个MyJobFactory 自定义JobFactory 类别并实现IJobFactory ,如下所示:
public class MyJobFactory : IJobFactory{ private readonly IServiceProvider _serviceProvider; public MyJobFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob; } public void ReturnJob(IJob job) { var disposable = job as IDisposable; disposable?.Dispose(); }}
接下来, 我们创建自己的Schedule 物件, 如下所示:
public class MyScheduler : IMyScheduler{ StdSchedulerFactory _scheduler; public MyScheduler(IJobFactory myJobFactory) { _scheduler = new StdSchedulerFactory() .GetScheduler() .Result; _scheduler.JobFactory = myJobFactory; } public void Start() { var job = CreateJob<MyJob>(); var trigger = TriggerBuilder.Create() .StartNow() .WithCronSchedule("0/10 ...") .Build(); _scheduler.ScheduleJob(job, trigger); _scheduler.Start(); } private IJobDetail CreateJob<T>() where T : IJob { return JobBuilder.Create<T>() .WithIdentity(typeof(T).Name) .Build(); }}
注意上面的程式码, 关键点在于这个地方
_scheduler.JobFactory = myJobFactory;
Quartz JobBuilder.Create() 方法将通过 myJobFactory 实例生成Job 物件.
然后我们在 Dotnet Project Startup.cs 档案中, 注册所有必需的类别.
public void ConfigureServices(IServiceCollection services){ //Blah.... services.AddTransient<IMyLogger, MyLogger>(); services.AddTransient<IJobFactory, MyJobFactory>(); services.AddSingleton<IMyScheduler, MyScheduler>();}
为了让程式码更容易阅读, 我们建立了一个扩充方法
public static class MyQuartzExtension { public static void UseQuartz(this IApplicationBuilder app) { var scheduler = app.ApplicationServices .GetService<IMyScheduler>(); scheduler.Start(); }}
最后我们在 startup.cs 中呼叫 UseQuartz()
public void Configure(IApplicationBuilder app, IHostingEnvironment env){ //Blah... app.UseQuartz();}
现在我们完成了这个伟大的任务 "DI 自动注入 Quartz Job 所需的依赖物件" !!