Solution 1:

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

Solution 2:

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

Solution 3:

I know it's an old question, but just wanted to add a 2020 answer:

https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/microsoft-di-integration.html

https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/aspnet-core-integration.html

I find it even easier than the approach that is not using the .NET Core DI. In the project I had to integrate it however, Autofac was using together with MS DI (can't tell you why) and it was complaining about some dependencies, so I had to add the following mapping as well:

services.AddSingleton<ITypeLoadHelper, SimpleTypeLoadHelper>();

The total solution for me looks like this:

services.AddTransient<UpcomingReleasesNotificationJob>();
services.AddSingleton<ITypeLoadHelper, SimpleTypeLoadHelper>();

var jobKey = new JobKey("notificationJob");
services.AddQuartz(q =>
{
   q.SchedulerId = "JobScheduler";
   q.SchedulerName = "Job Scheduler";
   q.UseMicrosoftDependencyInjectionScopedJobFactory();
   q.AddJob<UpcomingReleasesNotificationJob>(j => j.WithIdentity(jobKey));
   q.AddTrigger(t => t
      .WithIdentity("notificationJobTrigger")
      .ForJob(jobKey)
      .StartNow()
      .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(14, 00))
   );
});

services.AddQuartzServer(options =>
{
   options.WaitForJobsToComplete = true;
});