Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.net Core Quartz Dependency Injection

How can I configure Quartz in .net core to use dependency injection? I using standard .net core Dependency mechanism. In constructor of class that implements IJob, I need inject some dependencies.

like image 292
donex93 Avatar asked Feb 10 '17 11:02

donex93


People also ask

What dependency injection does .NET core use?

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. For more information specific to dependency injection within MVC controllers, see Dependency injection into controllers in ASP.NET Core.

What is Quartz in .NET core?

Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems. It's an old staple of many ASP.NET developers, used as a way of running background tasks on a timer, in a reliable, clustered, way.

What is Quartz Scheduler C#?

What is QUARTZ? Quartz.Net is a . NET port of the popular Java job scheduling framework. It's an open source job scheduling system that can be used from the smallest apps to the large-scale enterprise systems.


2 Answers

You can use the Quartz.Spi.IJobFactory interface and implement it. The Quartz documentations states:

When a trigger fires, the Job it is associated to is instantiated via the JobFactory configured on the Scheduler. The default JobFactory simply activates a new instance of the job class. You may want to create your own implementation of JobFactory to accomplish things such as having your application’s IoC or DI container produce/initialize the job instance. See the IJobFactory interface, and the associated Scheduler.SetJobFactory(fact) method.

ISchedulerFactory schedulerFactory = new StdSchedulerFactory(properties); var scheduler = schedulerFactory.GetScheduler();  scheduler.JobFactory = jobFactory; 

Edit

The implementation can look like this:

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     } } 

To use it with the Microsoft.Extensions.DependencyInjection create your container like this:

var services = new ServiceCollection(); services.AddTransient<IAuthorizable, AuthorizeService>(); var container = services.BuildServiceProvider(); var jobFactory = new JobFactory(container); 

References

  1. Quartz documentation

  2. Api

like image 135
Rabban Avatar answered Sep 24 '22 17:09

Rabban


Inspired by Rabbans great answer I created a complete implementation of a JobFactory for Microsoft.Extensions.DependencyInjection:

Implementation

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();         }     } } 

Usage

// 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; 

The implementation has been tested in a .NET Core 2.1 console application with a single job and worked fine. Feel free to leave your feedback or improvement suggestions...

like image 20
CodeZombie Avatar answered Sep 22 '22 17:09

CodeZombie