iT邦幫忙

0

如何使用Dotnet Core DI注入Quartz Job所需的依賴物件?

有一天,小明來問我這個問題:

如何使用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 所需的依賴物件" !!


尚未有邦友留言

立即登入留言