web-dev-qa-db-ja.com

.net Core Quartz Dependency Injection

依存関係注入を使用するように。netコアでQuartzを構成するにはどうすればよいですか?標準の.netコア依存関係メカニズムを使用しています。 IJobを実装するクラスのコンストラクターで、いくつかの依存関係を注入する必要があります。

12
donex93

Quartz.Spi.IJobFactoryインターフェースを使用して実装できます。 Quartzのドキュメントには次のように記載されています。

トリガーが起動すると、関連付けられているジョブは、スケジューラで構成されたJobFactoryを介してインスタンス化されます。デフォルトのJobFactoryは、単にジョブクラスの新しいインスタンスをアクティブ化します。アプリケーションのIoCまたはDIコンテナにジョブインスタンスを生成/初期化させるなどの目的を達成するために、JobFactoryの独自の実装を作成したい場合があります。 IJobFactoryインターフェースおよび関連するScheduler.SetJobFactory(fact)メソッドを参照してください。

ISchedulerFactory schedulerFactory = new StdSchedulerFactory(properties);
var scheduler = schedulerFactory.GetScheduler();

scheduler.JobFactory = jobFactory;

編集

実装は次のようになります。

public class JobFactory : IJobFactory
{
    protected readonly IServiceProvider Container;

    public JobFactory(IServiceProvider container)
    {
        Container = container;
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        return Container.GetService(bundle.JobDetail.JobType) as IJob;
    }

    public void ReturnJob(IJob job)
    {
        // i couldn't find a way to release services with your preferred DI, 
        // its up to you to google such things
    }
}

Microsoft.Extensions.DependencyInjectionで使用するには、次のようにコンテナを作成します。

var services = new ServiceCollection();
services.AddTransient<IAuthorizable, AuthorizeService>();
var container = services.BuildServiceProvider();
var jobFactory = new JobFactory(container);

参照

  1. Quartzドキュメント

  2. API

13
Rabban

Rabbansの素晴らしい答えに触発されましたMicrosoft.Extensions.DependencyInjectionのJobFactoryの完全な実装を作成しました:

実装

using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Spi;
using System;
using System.Collections.Concurrent;

class JobFactory : IJobFactory
{
    protected readonly IServiceProvider _serviceProvider;

    protected readonly ConcurrentDictionary<IJob, IServiceScope> _scopes = new ConcurrentDictionary<IJob, IServiceScope>();

    public JobFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        var scope = _serviceProvider.CreateScope();
        IJob job;

        try
        {
            job = scope.ServiceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
        }
        catch
        {
            // Failed to create the job -> ensure scope gets disposed
            scope.Dispose();
            throw;
        }

        // Add scope to dictionary so we can dispose it once the job finishes
        if (!_scopes.TryAdd(job, scope))
        {
            // Failed to track DI scope -> ensure scope gets disposed
            scope.Dispose();
            throw new Exception("Failed to track DI scope");
        }

        return job;
    }

    public void ReturnJob(IJob job)
    {
        if (_scopes.TryRemove(job, out var scope))
        {
            // The Dispose() method ends the scope lifetime.
            // Once Dispose is called, any scoped services that have been resolved from ServiceProvider will be disposed.
            scope.Dispose();
        }
    }
}

使用法

// Prepare the DI container
var services = new ServiceCollection();
// Register job
services.AddTransient<MyJob>();
// Register job dependencies
services.AddTransient<IFoo, Foo>();
var container = services.BuildServiceProvider();

// Create an instance of the job factory
var jobFactory = new JobFactory(container);

// Create a Quartz.NET scheduler
var schedulerFactory = new StdSchedulerFactory(properties);
var scheduler = schedulerFactory.GetScheduler();

// Tell the scheduler to use the custom job factory
scheduler.JobFactory = jobFactory;

実装は.NET Core 2.1コンソールアプリケーションで単一のジョブでテストされ、問題なく動作しました。あなたのフィードバックや改善提案を残してお気軽に...

4
CodeZombie

これが役立つかどうかはわかりませんが、Quartz用に独自のDI拡張機能を作成しました。ぜひ試してみてください。 https://github.com/JaronrH/Quartz.DependencyInjection

短いバージョンでは、AddQuartz()メソッドを使用して、[オプション] NaveValueCollection構成と、必要なScrutorアセンブリ検索を渡します( https://andrewlock.net/using-scrutor-to-を参照)。自動登録-あなたのサービス-と-その-asp-net-core-di-container / )。例えば:

services.AddQuartz(s => s.FromAssemblyOf<Program>())

この呼び出しは:

  • アセンブリ(Scrutor)にあるすべてのIJob、IAddScheduledJob、IAddSchedulerListener、IAddTriggerListener、およびIAddJobListener実装を検索して自動的に登録します。したがって、はい、IJobクラスでこのようにDIを使用できます。
  • 上記のDIリソースを使用するシングルトンISchedulerをDIでセットアップします。
  • ISchedulerにアダプターを登録して、MicrosoftのログがQuartzのログに使用されるようにします。

次に、provider.StartQuartz()を使用してスケジューラを開始し(IApplicationLifetimeを自動的に検索し、利用可能な場合はシャットダウン用にスケジューラを登録します)、従来のDIを使用してサービスを取得および開始します(provider.GetService()。Start(); )。

お役に立てれば!

1
Jaron