Quartz.Net 依赖注入 .Net Core
Quartz.Net Dependency Injection .Net Core
在我的项目中我必须使用 Quartz 但我不知道我做错了什么。
工作工厂:
public class IoCJobFactory : IJobFactory
{
private readonly IServiceProvider _factory;
public IoCJobFactory(IServiceProvider factory)
{
_factory = factory;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _factory.GetService(bundle.JobDetail.JobType) as IJob;
}
public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
石英扩展:
public static class QuartzExtensions
{
public static void UseQuartz(this IApplicationBuilder app)
{
app.ApplicationServices.GetService<IScheduler>();
}
public static async void AddQuartz(this IServiceCollection services)
{
var props = new NameValueCollection
{
{"quartz.serializer.type", "json"}
};
var factory = new StdSchedulerFactory(props);
var scheduler = await factory.GetScheduler();
var jobFactory = new IoCJobFactory(services.BuildServiceProvider());
scheduler.JobFactory = jobFactory;
await scheduler.Start();
services.AddSingleton(scheduler);
}
}
当我尝试 运行 我的工作时(class 有依赖注入)我总是得到异常,因为:
_factory.GetService(bundle.JobDetail.JobType) as IJob;
始终为空。
我的 class 实现 IJob
并在 startup.cs 中添加:
services.AddScoped<IJob, HelloJob>();
services.AddQuartz();
和
app.UseQuartz();
我使用标准的 .net Core 依赖注入:
using Microsoft.Extensions.DependencyInjection;
我在申请中就是这样做的。我没有将调度程序添加到 ioc,而是只添加了工厂
services.AddTransient<IJobFactory, AspJobFactory>(
(provider) =>
{
return new AspJobFactory( provider );
} );
我的工作工厂看起来几乎一样。瞬态并不重要,因为我只用过一次。那么我使用Quartz扩展的方法是
public static void UseQuartz(this IApplicationBuilder app, Action<Quartz> configuration)
{
// Job Factory through IOC container
var jobFactory = (IJobFactory)app.ApplicationServices.GetService( typeof( IJobFactory ) );
// Set job factory
Quartz.Instance.UseJobFactory( jobFactory );
// Run configuration
configuration.Invoke( Quartz.Instance );
// Run Quartz
Quartz.Start();
}
Quartz
class也是单例。
这只是我解决 IoC 问题的简单示例:
JobFactory.cs
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)
{
(job as IDisposable)?.Dispose();
}
}
Startup.cs
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IApplicationLifetime lifetime,
IServiceProvider container)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseMvc();
// the following 3 lines hook QuartzStartup into web host lifecycle
var quartz = new QuartzStartup(container);
lifetime.ApplicationStarted.Register(quartz.Start);
lifetime.ApplicationStopping.Register(quartz.Stop);
}
石英Startup.cs
public class QuartzStartup
{
private IScheduler _scheduler; // after Start, and until shutdown completes, references the scheduler object
private readonly IServiceProvider container;
public QuartzStartup(IServiceProvider container)
{
this.container = container;
}
// starts the scheduler, defines the jobs and the triggers
public void Start()
{
if (_scheduler != null)
{
throw new InvalidOperationException("Already started.");
}
var schedulerFactory = new StdSchedulerFactory();
_scheduler = schedulerFactory.GetScheduler().Result;
_scheduler.JobFactory = new JobFactory(container);
_scheduler.Start().Wait();
var voteJob = JobBuilder.Create<VoteJob>()
.Build();
var voteJobTrigger = TriggerBuilder.Create()
.StartNow()
.WithSimpleSchedule(s => s
.WithIntervalInSeconds(60)
.RepeatForever())
.Build();
_scheduler.ScheduleJob(voteJob, voteJobTrigger).Wait();
}
// initiates shutdown of the scheduler, and waits until jobs exit gracefully (within allotted timeout)
public void Stop()
{
if (_scheduler == null)
{
return;
}
// give running jobs 30 sec (for example) to stop gracefully
if (_scheduler.Shutdown(waitForJobsToComplete: true).Wait(30000))
{
_scheduler = null;
}
else
{
// jobs didn't exit in timely fashion - log a warning...
}
}
}
考虑一下你应该提前将你的服务注册到容器中(在我的例子中是 VoteJob)。
我是根据这个answer.
实现的
我希望它能有所帮助。
我遇到了同样的问题。
我从
更新
services.AddScoped<IJob, HelloJob>();
到
services.AddScoped<HelloJob>();
然后就可以了。
_factory.GetService(bundle.JobDetail.JobType) as IJob;
不会为空 :)
Quartz.NET 3.1 将包括对 Microsoft DI 和 ASP.NET 核心托管服务的官方支持。
您可以找到重新访问的包:
- Quartz.Extensions.DependencyInjection - Microsoft DI 集成
- Quartz.AspNetCore - ASP.NET 核心整合
查看正在进行的新 DI 集成的最佳资源是前往 the example ASP.NET Core application。
https://www.quartz-scheduler.net/2020/07/08/quartznet-3-1-beta-1-released/
在我的项目中我必须使用 Quartz 但我不知道我做错了什么。
工作工厂:
public class IoCJobFactory : IJobFactory
{
private readonly IServiceProvider _factory;
public IoCJobFactory(IServiceProvider factory)
{
_factory = factory;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _factory.GetService(bundle.JobDetail.JobType) as IJob;
}
public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
石英扩展:
public static class QuartzExtensions
{
public static void UseQuartz(this IApplicationBuilder app)
{
app.ApplicationServices.GetService<IScheduler>();
}
public static async void AddQuartz(this IServiceCollection services)
{
var props = new NameValueCollection
{
{"quartz.serializer.type", "json"}
};
var factory = new StdSchedulerFactory(props);
var scheduler = await factory.GetScheduler();
var jobFactory = new IoCJobFactory(services.BuildServiceProvider());
scheduler.JobFactory = jobFactory;
await scheduler.Start();
services.AddSingleton(scheduler);
}
}
当我尝试 运行 我的工作时(class 有依赖注入)我总是得到异常,因为:
_factory.GetService(bundle.JobDetail.JobType) as IJob;
始终为空。
我的 class 实现 IJob
并在 startup.cs 中添加:
services.AddScoped<IJob, HelloJob>();
services.AddQuartz();
和
app.UseQuartz();
我使用标准的 .net Core 依赖注入:
using Microsoft.Extensions.DependencyInjection;
我在申请中就是这样做的。我没有将调度程序添加到 ioc,而是只添加了工厂
services.AddTransient<IJobFactory, AspJobFactory>(
(provider) =>
{
return new AspJobFactory( provider );
} );
我的工作工厂看起来几乎一样。瞬态并不重要,因为我只用过一次。那么我使用Quartz扩展的方法是
public static void UseQuartz(this IApplicationBuilder app, Action<Quartz> configuration)
{
// Job Factory through IOC container
var jobFactory = (IJobFactory)app.ApplicationServices.GetService( typeof( IJobFactory ) );
// Set job factory
Quartz.Instance.UseJobFactory( jobFactory );
// Run configuration
configuration.Invoke( Quartz.Instance );
// Run Quartz
Quartz.Start();
}
Quartz
class也是单例。
这只是我解决 IoC 问题的简单示例:
JobFactory.cs
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)
{
(job as IDisposable)?.Dispose();
}
}
Startup.cs
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IApplicationLifetime lifetime,
IServiceProvider container)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseMvc();
// the following 3 lines hook QuartzStartup into web host lifecycle
var quartz = new QuartzStartup(container);
lifetime.ApplicationStarted.Register(quartz.Start);
lifetime.ApplicationStopping.Register(quartz.Stop);
}
石英Startup.cs
public class QuartzStartup
{
private IScheduler _scheduler; // after Start, and until shutdown completes, references the scheduler object
private readonly IServiceProvider container;
public QuartzStartup(IServiceProvider container)
{
this.container = container;
}
// starts the scheduler, defines the jobs and the triggers
public void Start()
{
if (_scheduler != null)
{
throw new InvalidOperationException("Already started.");
}
var schedulerFactory = new StdSchedulerFactory();
_scheduler = schedulerFactory.GetScheduler().Result;
_scheduler.JobFactory = new JobFactory(container);
_scheduler.Start().Wait();
var voteJob = JobBuilder.Create<VoteJob>()
.Build();
var voteJobTrigger = TriggerBuilder.Create()
.StartNow()
.WithSimpleSchedule(s => s
.WithIntervalInSeconds(60)
.RepeatForever())
.Build();
_scheduler.ScheduleJob(voteJob, voteJobTrigger).Wait();
}
// initiates shutdown of the scheduler, and waits until jobs exit gracefully (within allotted timeout)
public void Stop()
{
if (_scheduler == null)
{
return;
}
// give running jobs 30 sec (for example) to stop gracefully
if (_scheduler.Shutdown(waitForJobsToComplete: true).Wait(30000))
{
_scheduler = null;
}
else
{
// jobs didn't exit in timely fashion - log a warning...
}
}
}
考虑一下你应该提前将你的服务注册到容器中(在我的例子中是 VoteJob)。
我是根据这个answer.
实现的
我希望它能有所帮助。
我遇到了同样的问题。
我从
更新services.AddScoped<IJob, HelloJob>();
到
services.AddScoped<HelloJob>();
然后就可以了。
_factory.GetService(bundle.JobDetail.JobType) as IJob;
不会为空 :)
Quartz.NET 3.1 将包括对 Microsoft DI 和 ASP.NET 核心托管服务的官方支持。
您可以找到重新访问的包:
- Quartz.Extensions.DependencyInjection - Microsoft DI 集成
- Quartz.AspNetCore - ASP.NET 核心整合
查看正在进行的新 DI 集成的最佳资源是前往 the example ASP.NET Core application。
https://www.quartz-scheduler.net/2020/07/08/quartznet-3-1-beta-1-released/