don*_*x93 12 .net c# dependency-injection quartz.net asp.net-core
如何在.net内核中配置Quartz 以使用依赖注入?我使用标准的.net核心依赖机制.在实现IJob的类的构造函数中,我需要注入一些依赖项.
Rab*_*ban 15
您可以使用该Quartz.Spi.IJobFactory
界面并实现它.Quartz文件指出:
触发器触发时,与其关联的作业将通过Scheduler上配置的JobFactory实例化.默认的JobFactory只是激活作业类的新实例.您可能希望创建自己的JobFactory实现来完成诸如让应用程序的IoC或DI容器生成/初始化作业实例之类的事情.请参阅IJobFactory接口和相关的Scheduler.SetJobFactory(fact)方法.
ISchedulerFactory schedulerFactory = new StdSchedulerFactory(properties);
var scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = jobFactory;
Run Code Online (Sandbox Code Playgroud)
编辑
实现可能如下所示:
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
}
}
Run Code Online (Sandbox Code Playgroud)
要Microsoft.Extensions.DependencyInjection
像创建容器一样使用它:
var services = new ServiceCollection();
services.AddTransient<IAuthorizable, AuthorizeService>();
var container = services.BuildServiceProvider();
var jobFactory = new JobFactory(container);
Run Code Online (Sandbox Code Playgroud)
参考
Dan*_*off 14
我知道这是一个老问题,但只是想添加一个 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>();
Run Code Online (Sandbox Code Playgroud)
我的总解决方案如下所示:
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;
});
Run Code Online (Sandbox Code Playgroud)
受Rabbans出色答案的启发,我为以下项目创建了JobFactory的完整实现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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
// 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;
Run Code Online (Sandbox Code Playgroud)
该实现已在.NET Core 2.1控制台应用程序中通过一项工作进行了测试,并且运行良好。随时留下您的反馈或改进建议...
归档时间: |
|
查看次数: |
7641 次 |
最近记录: |