#c# #dependency-injection #quartz-scheduler
#c# #внедрение зависимостей #quartz.net
Вопрос:
Я работаю над своим первым проектом с EF Core и внедрением зависимостей для контекста БД. Однако я сталкиваюсь с проблемой, потому что Quartz.net 3, похоже, не допускает никаких параметров в классе ImportJob. Итак, мой метод DI в этом случае не работает. Я знаю, что мне нужен новый контекст, потому что это будет выполняться в фоновом режиме, есть ли другой способ создать контекст БД, чтобы я мог выполнить эту задачу?
public class ImportJob : IJob
{
private readonly SContext _db;
//Quartz.net doesn't appear to like that I'm injecting these,
//because if I remove this parameter, execute...executes.
public ImportJob(SContext db)
{
_db = db;
}
public Task Execute(IJobExecutionContext context)
{
var cc = new CC(_db);
return Task.CompletedTask;
}
}
Ответ №1:
Один из способов — использовать StdSchedulerFactory, фабрику заданий, которая реализует IJobFactory и использует IServiceProvider
Пример
public class JobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public JobFactory(IServiceProvider serviceProvider)
=> _serviceProvider = serviceProvider;
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
var jobDetail = bundle.JobDetail;
var jobType = jobDetail.JobType;
return _serviceProvider.GetService(jobType) as IJob;
}
catch (Exception ex)
{
throw new SchedulerException($"Problem instantiating class '{bundle.JobDetail.JobType.FullName}'", ex);
}
}
public void ReturnJob(IJob job)
=> (job as IDisposable)?.Dispose();
}
В зависимости от вашей инфраструктуры DI регистрации будут выглядеть примерно так
// register, your container as an IServiceProvider
container.RegisterInstance<IServiceProvider>(container);
// create the scheduler
var scheduler = await StdSchedulerFactory.GetDefaultScheduler(cancellationTokenSource.Token);
// add your factory to the scheduler
scheduler.JobFactory = new JobFactory(container);
// register the scheduler
container.RegisterInstance(scheduler);
// register your jobs
container.Collection.Register<IJob>(GetType().Assembly);
Тогда ваши задания могут выглядеть следующим образом
public class ImportJob : IJob
{
private readonly SContext _db;
//Quartz.net doesn't appear to like that I'm injecting these,
//because if I remove this parameter, execute...executes.
public ImportJob(SContext db)
{
_db = db;
}
public Task Execute(IJobExecutionContext context)
{
var cc = new CC(_db);
return Task.CompletedTask;
}
}
Примечание: Это основная идея, а не полный пример, и это будет во многом зависеть от ваших собственных настроек и фреймворка
Короче говоря, то, что вышеописанное делает, — это когда Quartz создает задание, оно использует вашу фабрику и контейнер для запуска задания, допускающего внедрение.
Комментарии:
1. Я новичок в DI amp; EF Core, я не вижу, где находится моя _db в вашем примере?
2. @JoeStellato Это проблема DI / Quartz, а не проблема с заданиями. что он делает, так это позволяет вашим заданиям поддерживать DI. он делает это, используя вашу собственную фабрику заданий и ваш контейнер для запуска задания и DI