-
-
Save Antaris/9c3c097d31a90da279e3e6d78497a369 to your computer and use it in GitHub Desktop.
| 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 _); | |
| } | |
| } | |
| } |
Why the factory pattern must be used? Are there other ways to achieve the same result in a much cleaner way?
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/
Quartz now has a baked in solution using their new
Quartz.Extensions.Hostingpackagehttps://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 :)
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.
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...