.net Core Quartz Dependency Injection

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


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