简述
有时会遇到需要在IJob实现类中依赖注入其他类或接口的情况,但Quartz的默认JobFactory并不能识别具有有参构造函数的IJob实现类,也就无法进行依赖注入
注:该情况通常出现在低版本中,较高版本中可以通过以下方式开启依赖注入支持,更高的版本中默认使用DI而无需使用该函数,且该函数会在未来被移除(具体的版本分界线我并不清楚)
builder.Services.AddQuartz(q =>
{
q.UseMicrosoftDependencyInjectionJobFactory();
......
需要被依赖注入的类:
public class TestClass
{
public TestClass(Type jobType, string cronExpression)
{
JobType = jobType;
CronExpression = cronExpression;
}
public Type JobType { get; }
public string CronExpression { get; }
}
解决方式
1.安装依赖:Quartz、Microsoft.Extensions.DependencyInjection
2.实现接口
实现IJob接口
public class MyJob : IJob
{
private readonly TestClass test;
public MyJob(TestClass test)
{
this.test = test;
}
public Task Execute(IJobExecutionContext context)
{
Console.WriteLine("hello");
Console.WriteLine(test.ToString());
return Task.CompletedTask;
}
}
实现IJobFactory接口
public class MyJobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public MyJobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
}
public void ReturnJob(IJob job) { }
}
3.将IJob实现类、IJobFactory实现类、需要被依赖注入的类(TestClass)添加进容器
private static ServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
services.AddSingleton<MyJob>();
services.AddSingleton<IJobFactory, MyJobFactory>();
services.AddSingleton(new TestClass(
jobType: typeof(MyJob),
cronExpression: "0/5 * * * * ?"));
return services.BuildServiceProvider();
}
4.将scheduler的JobFactory属性替换为IJobFactory实现类的实例
var scheduler = await StdSchedulerFactory.GetDefaultScheduler();
// JobFactory替换为IJobFactory实现类的实例
scheduler.JobFactory = serviceProvider.GetService<IJobFactory>();
5.测试
static async Task Main(string[] args)
{
var serviceProvider = ConfigureServices();
var scheduler = await StdSchedulerFactory.GetDefaultScheduler();
// JobFactory替换为IJobFactory实现类的实例
scheduler.JobFactory = serviceProvider.GetService<IJobFactory>();
var jobSchedule = serviceProvider.GetService<TestClass>();
var jobDetail = JobBuilder.Create(jobSchedule.JobType).Build();
var trigger = TriggerBuilder.Create()
.WithCronSchedule(jobSchedule.CronExpression)
.Build();
await scheduler.ScheduleJob(jobDetail, trigger);
await scheduler.Start();
Thread.Sleep(10000);
}