如何在 .net 核心中配置Quartz以使用依赖注入?我使用标准的.net核心依赖机制。在实现 IJob 的类的构造函数中,我需要注入一些依赖项。
答案 0 :(得分:10)
您可以使用Quartz.Spi.IJobFactory
界面并实施它。 Quartz文档声明:
当触发器触发时,与其关联的Job将通过Scheduler上配置的JobFactory实例化。默认的JobFactory只是激活作业类的新实例。您可能希望创建自己的JobFactory实现来完成诸如让应用程序的IoC或DI容器生成/初始化作业实例之类的事情。 请参阅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 :(得分:7)
我知道这是一个老问题,但只想添加一个2020年答案:
https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/microsoft-di-integration.html
https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/aspnet-core-integration.html
我发现它比不使用.NET Core DI的方法更加容易。 但是,在我必须集成的项目中,Autofac与MS DI一起使用(无法告诉您原因),并且抱怨某些依赖性,因此我还必须添加以下映射:
services.AddSingleton<ITypeLoadHelper, SimpleTypeLoadHelper>();
对我来说,总体解决方案如下:
services.AddTransient<UpcomingReleasesNotificationJob>();
services.AddSingleton<ITypeLoadHelper, SimpleTypeLoadHelper>();
var jobKey = new JobKey("notificationJob");
services.AddQuartz(q =>
{
q.SchedulerId = "JobScheduler";
q.SchedulerName = "Job Scheduler";
q.UseMicrosoftDependencyInjectionScopedJobFactory();
q.AddJob<UpcomingReleasesNotificationJob>(j => j.WithIdentity(jobKey));
q.AddTrigger(t => t
.WithIdentity("notificationJobTrigger")
.ForJob(jobKey)
.StartNow()
.WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(14, 00))
);
});
services.AddQuartzServer(options =>
{
options.WaitForJobsToComplete = true;
});
答案 2 :(得分:1)
受Rabbans great answer的启发,我为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();
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控制台应用程序中通过一项工作进行了测试,并且工作良好。 随时留下您的反馈或改进建议...
答案 3 :(得分:1)
不知道这是否会有所帮助,但我为Quartz创建了自己的DI扩展名,欢迎您尝试:https://github.com/JaronrH/Quartz.DependencyInjection
简短版本是,您将使用AddQuartz()方法传递所需的[可选] NaveValueCollection配置和[必需] Scrutor程序集搜索(请参阅https://andrewlock.net/using-scrutor-to-automatically-register-your-services-with-the-asp-net-core-di-container/)。例如:
services.AddQuartz(s => s.FromAssemblyOf<Program>())
此呼叫将:
然后,您可以使用provider.StartQuartz()启动调度程序(它将自动查找IApplicationLifetime并注册调度程序以进行关机(如果可用)),也可以使用常规DI来获取和启动服务(provider.GetService()。Start)。 ();)。
希望这会有所帮助!