依存関係注入を使用するように。netコアでQuartzを構成するにはどうすればよいですか?標準の.netコア依存関係メカニズムを使用しています。 IJobを実装するクラスのコンストラクターで、いくつかの依存関係を注入する必要があります。
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);
参照
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コンソールアプリケーションで単一のジョブでテストされ、問題なく動作しました。あなたのフィードバックや改善提案を残してお気軽に...
これが役立つかどうかはわかりませんが、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>())
この呼び出しは:
次に、provider.StartQuartz()を使用してスケジューラを開始し(IApplicationLifetimeを自動的に検索し、利用可能な場合はシャットダウン用にスケジューラを登録します)、従来のDIを使用してサービスを取得および開始します(provider.GetService()。Start(); )。
お役に立てれば!