Skip to content

Instantly share code, notes, and snippets.

@Antaris
Created May 21, 2019 19:57
Show Gist options
  • Save Antaris/9c3c097d31a90da279e3e6d78497a369 to your computer and use it in GitHub Desktop.
Save Antaris/9c3c097d31a90da279e3e6d78497a369 to your computer and use it in GitHub Desktop.
A Quartz.NET job factory using Microsoft.Extensions.DependencyInjection and scoped services
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Spi;
public class ServiceProviderJobFactory : IJobFactory
{
private readonly IServiceProvider _rootServiceProvider;
private ConcurrentDictionary<Type, IServiceScope> _scopes = new ConcurrentDictionary<Type, IServiceScope>();
public ServiceProviderJobFactory(IServiceProvider rootServiceProvider)
{
_rootServiceProvider = rootServiceProvider ?? throw new ArgumentNullException(rootServiceProvider);
}
public IJob NewJob(TriggerFireBundle bundle, IScheduler scheduler)
{
var jobType = bundle.JobDetail.JobType;
// MA - Generate a scope for the job, this allows the job to be registered
// using .AddScoped<T>() which means we can use scoped dependencies
// e.g. database contexts
var scope = _scopes.GetOrAdd(jobType, t => _rootServiceProvider.CreateScope());
return (IJob)scope.ServiceProvider.GetRequiredService(jobType);
}
public void ReturnJob(IJob job)
{
var jobType = job?.GetType();
if (job != null && _scopes.TryGetValue(jobType, out var scope)
{
// MA - Dispose of the scope, which disposes of the job's dependencies
scope.Dispose();
// MA - Remove the scope so the next time the job is resolved,
// we can get a new job instance
_scopes.TryRemove(jobType, out _);
}
}
}
@AndyPook
Copy link

How about https://github.com/AndyPook/QuartzHostedService/blob/master/QuartzHostedService/ScopedJobFactory.cs as another alternative?
Tightly associates the scope with the job, avoids the dictionary...

@RuslanPr0g
Copy link

Why the factory pattern must be used? Are there other ways to achieve the same result in a much cleaner way?

@Antaris
Copy link
Author

Antaris commented Feb 19, 2021

Quartz now has a baked in solution using their new Quartz.Extensions.Hosting package

https://andrewlock.net/using-quartz-net-with-asp-net-core-and-worker-services/

@RuslanPr0g
Copy link

Quartz now has a baked in solution using their new Quartz.Extensions.Hosting package

https://andrewlock.net/using-quartz-net-with-asp-net-core-and-worker-services/

Thank you, I literally have found that blog at the same time you wrote me :)

@td28354
Copy link

td28354 commented Mar 2, 2021

I checked the provided link about Quartz.Extensions.Hosting but what happens If I need to create jobs based on some information received after the worker service is started.
Let's say I have a BackgroundService hosted in a windows service and this windows service is responsible for creating new jobs based on some information received from other applications, let's say, a desktop application; unfortunately the above link about Quartz.Extensions.Hosting, does not help at all. Please correct me if I'm wrong.

Thanks, AndyPook for the provided sample.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment