使用 Quartz.NET 和 Simple Injector 进行构造函数注入
Posted
技术标签:
【中文标题】使用 Quartz.NET 和 Simple Injector 进行构造函数注入【英文标题】:Constructor injection with Quartz.NET and Simple Injector 【发布时间】:2013-01-11 19:11:45 【问题描述】:目前我正在使用 Quartz.NET 编写一个服务来安排它的运行。
我想知道是否有人有使用 Quartz.NET 和 Simple Injector 的构造函数注入的经验。
以下基本上是我希望实现的目标
public class JobImplementation: IJob
private readonly IInjectedClass injectedClass;
public JobImplementation(IInjectedClass _injectedClass)
injectedClass = _injectedClass
public void Execute(IJobExecutionContext _context)
//Job code
【问题讨论】:
【参考方案1】:根据this blog post,您需要实现一个自定义IJobFactory
,如下所示:
public class SimpleInjectorJobFactory : IJobFactory
private readonly Container container;
private readonly Dictionary<Type, InstanceProducer> jobProducers;
public SimpleInjectorJobFactory(
Container container, params Assembly[] assemblies)
this.container = container;
// By creating producers, jobs can be decorated.
var transient = Lifestyle.Transient;
this.jobProducers =
container.GetTypesToRegister(typeof(IJob), assemblies).ToDictionary(
type => type,
type => transient.CreateProducer(typeof(IJob), type, container));
public IJob NewJob(TriggerFiredBundle bundle, IScheduler _)
var jobProducer = this.jobProducers[bundle.JobDetail.JobType];
return new AsyncScopedJobDecorator(
this.container, () => (IJob)jobProducer.GetInstance());
public void ReturnJob(IJob job)
// This will be handled automatically by Simple Injector
private sealed class AsyncScopedJobDecorator : IJob
private readonly Container container;
private readonly Func<IJob> decorateeFactory;
public AsyncScopedJobDecorator(
Container container, Func<IJob> decorateeFactory)
this.container = container;
this.decorateeFactory = decorateeFactory;
public async Task Execute(IJobExecutionContext context)
using (AsyncScopedLifestyle.BeginScope(this.container))
var job = this.decorateeFactory();
await job.Execute(context);
此外,您还需要以下注册:
var container = new Container();
container.Options.ScopedLifestyle = new AsyncScopedLifestyle();
var factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
scheduler.JobFactory = new SimpleInjectorJobFactory(
container,
Assembly.GetExecutingAssembly()); // assemblies that contain jobs
// Optional: register some decorators
container.RegisterDecorator(typeof(IJob), typeof(LoggingJobDecorator));
container.Verify();
【讨论】:
谢谢。一个小问题,StdSchedulerFactory 类有 2 个构造函数,有没有告诉 simpleinjector 使用零参数构造函数? 我不得不搜索它并认为注意以下石英配置是您告诉它使用注入友好作业工厂实现的方式会有所帮助: 我必须以与上面稍有不同的方式注册调度程序才能放入 jobFactory。使用 XML 不起作用,因为它强制要求默认构造函数。因此,除了 Steven 的帖子之外,我还添加了 container.RegisterSinglepublic IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) ...
。并且不确定是否应该在public void ReturnJob(IJob job)...
中实现任何清理调用。
这似乎不适用于最新版本的 Quartz 和 SimpleInjector。我没有 ILoadServiceScheduler、TimerScheduler、LoggingJobDecorator。另外,我如何获得 applicationAssemblies?我在这里很困惑,无法弄清楚这一点。 :)【参考方案2】:
迟到了,但https://github.com/hbiarge/Quartz.Unity 非常适合结合 Quartz.NET 和 Unity。
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Quartz.Unity.QuartzUnityExtension>();
// do your other Unity registrations
IScheduler scheduler = container.Resolve<IScheduler>();
scheduler.ScheduleJob(
new JobDetailImpl(myCommandName, typeof(MyCommand)),
TriggerBuilder.Create()
.WithCronSchedule(myCronSchedule)
.StartAt(startTime)
.Build()
);
scheduler.Start();
【讨论】:
【参考方案3】:通过 asp.net 核心的依赖注入引擎使用 Quartz.net 只需几个步骤。
将 nuget 包添加到您的项目中:
Microsoft.Extensions.DependencyInjection
创建自定义 JobFactory:
public class JobFactory : IJobFactory
protected readonly IServiceProvider _serviceProvider;
public JobFactory(IServiceProvider serviceProvider)
=> _serviceProvider = serviceProvider;
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
=> _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob;
public void ReturnJob(IJob job)
=> (job as IDisposable)?.Dispose();
配置调度器时指定JobFactory:
var scheduler = await StdSchedulerFactory.GetDefaultScheduler();
scheduler.JobFactory = new JobFactory(_serviceProvider);
对于某人来说,在板上使用 Quartz.net 和 DI(来自 asp.net 核心)作为 win 服务的有用示例:
public class WinService : ServiceBase
private Scheduler _scheduleManager;
private readonly Startup _startup;
public WinService()
ServiceName = "SomeWinService";
_startup = new Startup();
static void Main(string[] args)
var service = new WinService();
// Working as Windows-service
if (Console.IsInputRedirected && Console.IsOutputRedirected)
ServiceBase.Run(service);
// Working as console app
else
service.OnStart(args);
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
service.OnStop();
protected override void OnStart(string[] args)
_startup.RegisterServices();
_scheduleManager = new Scheduler(_startup.ServiceProvider);
_scheduleManager.StartTracking().Wait();
protected override void OnPause()
=> _scheduleManager.PauseTracking().Wait();
protected override void OnContinue()
=> _scheduleManager.ResumeTracking().Wait();
protected override void OnStop()
_scheduleManager.StopTracking().Wait();
_startup.DisposeServices();
public class Startup
private IServiceProvider _serviceProvider;
public IServiceProvider ServiceProvider => _serviceProvider;
public void RegisterServices()
_serviceProvider = new ServiceCollection()
//.AddTransient(...)
//.AddScoped(...)
//.AddSingleton(...)
.BuildServiceProvider();
public void DisposeServices()
if (_serviceProvider == null)
return;
if (_serviceProvider is IDisposable)
((IDisposable)_serviceProvider).Dispose();
public class Scheduler
private readonly IServiceProvider _serviceProvider;
private IScheduler _scheduler;
public Scheduler(IServiceProvider serviceProvider)
=> _serviceProvider = serviceProvider;
public async Task StartTracking()
_scheduler = await StdSchedulerFactory.GetDefaultScheduler();
_scheduler.JobFactory = new JobFactory(_serviceProvider);
await _scheduler.Start();
// Schedule your jobs here
public async Task PauseTracking() => await _scheduler?.PauseAll();
public async Task ResumeTracking() => await _scheduler?.ResumeAll();
public async Task StopTracking() => await _scheduler?.Shutdown();
【讨论】:
以上是关于使用 Quartz.NET 和 Simple Injector 进行构造函数注入的主要内容,如果未能解决你的问题,请参考以下文章