This applies to Quartz.NET version 1.0.3 that is also available on NuGet by package name "Quartz".
Jobs are implemented by implementing one of the job-interfaces IJob, IInterruptableJob or IStatefulJob (they are all based on IJob). The job is then registered with a scheduler and a trigger.
The initialization code below is also described in Lesson 1 of Quartz.NET tutorial:
// construct a scheduler factory ISchedulerFactory schedFact = new StdSchedulerFactory(); // get a scheduler IScheduler sched = schedFact.GetScheduler(); sched.Start(); // construct job info JobDetail jobDetail = new JobDetail("myJob", null, typeof(HelloJob)); // fire every hour Trigger trigger = TriggerUtils.MakeSecondlyTrigger(5); trigger.Name = "myTrigger"; sched.ScheduleJob(jobDetail, trigger);This is fine as long as the job doesn't require a dependency. But what if your Job implementation demands a dependency?
public class HelloJob : IJob { private readonly ILogger _logger; public HelloJob(ILogger logger) { _logger = logger; } public void Execute(JobExecutionContext context) { _logger.Log(@"Oh Hai \o/"); } }Then you need to roll your own IJobFactory implementation. My implementation with my favourite IoC container Castle Windsor is described below:
public class WindsorJobFactory : IJobFactory { private readonly IWindsorContainer _container; public WindsorJobFactory(IWindsorContainer container) { _container = container; } public IJob NewJob(TriggerFiredBundle bundle) { return (IJob)_container.Resolve(bundle.JobDetail.JobType); } }The JobFactory instance then needs to be assigned to the scheduler in the initialization code:
var container = new WindsorContainer(); IJobFactory jobFactory = new WindsorJobFactory(container); ISchedulerFactory schedFact = new StdSchedulerFactory(); IScheduler sched = schedFact.GetScheduler(); sched.JobFactory = jobFactory; sched.Start();I'm aware that you should not call your IoC-container directly, instead adhere to The Hollywood principle, but I think its ok in this case because it's the initialization of the infrastructure. The job implementations must also be registered with your IoC-container:
public class JobRegistrar { private readonly IWindsorContainer _container; public JobRegistrar(IWindsorContainer container) { _container = container; } private static IEnumerableThat's all for tonight folks! All code can be found on my GitHub accountGetJobTypes() { return AppDomain.CurrentDomain.GetAssemblies().ToList() .SelectMany(s => s.GetTypes()) .Where(p => typeof(IJob).IsAssignableFrom(p) && !p.IsInterface); } public void RegisterJobs() { var jobTypes = GetJobTypes(); foreach (Type jobType in jobTypes) { _container.Register(Component.For(jobType).ImplementedBy(jobType).LifeStyle.Transient); } } }
There's been a contrib project to integrate Quartz.NET and Windsor for 3 years now, please see http://bugsquash.blogspot.com/2009/03/windsor-facility-for-quartznet.html and https://github.com/castleprojectcontrib/QuartzNetIntegration . It supports a lot more than just managing jobs. Let's avoid the fragmentation of work efforts and work on this contrib project.
SvaraRaderaThank you for your comment!
RaderaThe contrib project looks nice, I will use it in the future for Windsor integration.
This blog post shows how to integrate Quartz.NET with any IoC container. The example is using Castle Windsor, it could have been any IoC.