Comment puis-je configurer Quartz dans . Net core pour utiliser l'injection de dépendance? J'utilise le mécanisme de dépendance standard .net core. Dans le constructeur de classe qui implémente IJob, j'ai besoin d'injecter quelques dépendances.
Vous pouvez utiliser le Quartz.Spi.IJobFactory
interface et l'implémenter. Les documentations Quartz indiquent:
Lorsqu'un déclencheur se déclenche, le Job auquel il est associé est instancié via JobFactory configuré sur le Planificateur. La JobFactory par défaut active simplement une nouvelle instance de la classe d'emplois. Vous souhaiterez peut-être créer votre propre implémentation de JobFactory pour accomplir des tâches telles que faire en sorte que le conteneur IoC ou DI de votre application produise/initialise l'instance de travail. Voir l'interface IJobFactory et la méthode Scheduler.SetJobFactory (fact) associée.
ISchedulerFactory schedulerFactory = new StdSchedulerFactory(properties);
var scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = jobFactory;
Modifier
L'implémentation peut ressembler à ceci:
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
}
}
Pour l'utiliser avec le Microsoft.Extensions.DependencyInjection
créez votre conteneur comme ceci:
var services = new ServiceCollection();
services.AddTransient<IAuthorizable, AuthorizeService>();
var container = services.BuildServiceProvider();
var jobFactory = new JobFactory(container);
Références
Inspiré par grande réponse de Rabbans J'ai créé une implémentation complète d'une JobFactory pour Microsoft.Extensions.DependencyInjection
:
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;
L'implémentation a été testée dans une application console .NET Core 2.1 avec un seul travail et a bien fonctionné. N'hésitez pas à laisser vos commentaires ou suggestions d'amélioration ...
Aucune idée si cela sera utile ou non, mais j'ai créé ma propre extension DI pour Quartz que vous êtes plus que bienvenu à essayer: https://github.com/JaronrH/Quartz.DependencyInjection
La version courte est que vous utiliseriez la méthode AddQuartz () pour passer la configuration [facultative] NaveValueCollection et l'assemblage Scrutor [requis] que vous recherchez (voir https://andrewlock.net/using-scrutor-to- enregistrer-automatiquement-vos-services-avec-le-conteneur-core-asp-net / ). Par exemple:
services.AddQuartz(s => s.FromAssemblyOf<Program>())
Cet appel:
Vous pouvez ensuite utiliser provider.StartQuartz () pour démarrer le planificateur (qui recherche automatiquement IApplicationLifetime et enregistre le planificateur pour l'arrêt si disponible) ou utilisez DI conventionnel pour obtenir et démarrer les services (provider.GetService (). Start (); ).
J'espère que cela t'aides!