Dependency Injection for Quartz.NET in .NET Core
Tags: quartznet, di, netcore, csharp
Published: 2019-06-23 16:09:51

---
title: Dependency Injection for Quartz.NET in .NET Core
published: true
description: The article shows how to perform dependency injection when using Quartz.NET library employing standard .NET Core DI container library. Also, we'll focus on a couple of other useful .NET core techniques.
tags: Quartz.NET, DI, netcore, Csharp
cover_image: https://cdn.pixabay.com/photo/2018/05/27/23/45/the-carpathians-3434944_960_720.jpg
---

The post was originally published at [codeproject](https://www.codeproject.com/Articles/1277745/Dependency-Injection-for-Quartz-NET-in-NET-Core)

##Introduction
Quartz.NET is a handy library that allows you to schedule recurring tasks via implementing `IJob` interface. Yet the limitation of it is that, by default, it supports only parameterless constructor which complicates injecting external service inside of it, i.e., for implementing [repository pattern](https://www.codeproject.com/Questions/1267495/How-to-implement-repository-pattern-to-quartz-job). In this article, we'll take a look at how we can tackle this problem using standard .NET Core DI container.

The whole project referred in the article is provided inside the following [Github repository](https://github.com/Wkalmar/QuartzDI.Demo). In order to better follow the code in the article, you might want to take a look at it.

##Project Overview
Let's take a look at the initial solution structure.

The project `QuartzDI.Demo.External.DemoService` represents some external dependency we have no control of. For the sake of simplicity, it does quite a humble job.

The project `QuartzDI.Demo` is our working project which contains simple Quartz.NET job.
```
public class DemoJob : IJob
{
    private const string Url = "https://i.ua";

    public static IDemoService DemoService { get; set; }

    public Task Execute(IJobExecutionContext context)
    {
        DemoService.DoTask(Url);
        return Task.CompletedTask;
    }
}
```
which is set up in a straightforward way:
```
var props = new NameValueCollection
{
    { "quartz.serializer.type", "binary" }
};
var factory = new StdSchedulerFactory(props);
var sched = await factory.GetScheduler();
await sched.Start();
var job = JobBuilder.Create<DemoJob>()
    .WithIdentity("myJob", "group1")
    .Build();
var trigger = TriggerBuilder.Create()
    .WithIdentity("myTrigger", "group1")
    .StartNow()
    .WithSimpleSchedule(x => x
        .WithIntervalInSeconds(5)
        .RepeatForever())
.Build();
await sched.ScheduleJob(job, trigger);
```
We provide our external service via job's `static` property
```
DemoJob.DemoService = new DemoService();
```
As the project is a console application, during the course of the article, we'll have to manually install all needed infrastructure and will be able to build more thorough understanding what actually .NET Core brings to our table.

At this point, our project is up and running. And what is most important it is dead simple which is great. But we pay for that simplicity with a cost of application inflexibility which is fine if we want to leave it as a small tool. But that's often not a case for production systems. So let's tweak it a bit to make it more flexible.

##Creating a Configuration File
One of the inflexibilities is that we hard-code URL we call into a `DemoJob`. Ideally, we would like to change it and also change it depending on our environment. .NET Core comes with appsettings.json mechanism for that matter.

In order to start working with .NET Core configuration mechanism, we have to install a couple of Nuget packages:
```
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.FileExtensions
Microsoft.Extensions.Configuration.Json
```
Let's create a file with such name and extract our URL there:

```
{
  "connection": {
    "Url": "https://i.ua"
  }
}
```
Now we can extract our value from the config file as follows:
```
var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", true, true);
var configuration = builder.Build();
var connectionSection = configuration.GetSection("connection");
DemoJob.Url = connectionSection["Url"];
```
Note that to make it happen, we had to change Url from constant to property.
```
public static string Url { get; set; }
```

##Using Constructor Injection
Injecting service via a `static` property is fine for a simple project, but for a bigger one, it might carry several disadvantages: such as job might be called without service provided thus failing or changing the dependency during the object runtime which makes it harder to reason about objects. To address these issues, we should employ constructor injection.

Although there is nothing wrong with Pure Dependency Injection and some people argue that you should strive for it in this article, we'll use built-in .NET Core DI container which comes with a Nuget package `Microsoft.Extensions.DependencyInjection`.

Now we specify service we depend on inside constructor arguments:
```
private readonly IDemoService _demoService;

public DemoJob(IDemoService demoService)
{
    _demoService = demoService;
}
```
In order to invoke a parameterful constructor of the job, Quartz.NET provides IJobFactory interface. Here's our implementation:

```
public class DemoJobFactory : IJobFactory
{
    private readonly IServiceProvider _serviceProvider;

    public DemoJobFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        return _serviceProvider.GetService<DemoJob>();
    }

    public void ReturnJob(IJob job)
    {
        var disposable = job as IDisposable;
        disposable?.Dispose();
    }
}
```
Let's register our dependencies:

```
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<DemoJob>();
serviceCollection.AddScoped<IDemoService, DemoService>();
var serviceProvider = serviceCollection.BuildServiceProvider();
```
The final piece of a puzzle is to make Quartz.NET use our factory. IScheduler has property JobFactory just for that matter.
```
sched.JobFactory = new DemoJobFactory(serviceProvider);
```

##Using Options Pattern
Now we can pull the same trick with configuration options. Again, our routine starts with a Nuget package. This time `Microsoft.Extensions.Options`.

Let's create a strongly typed definition for configuration options:
```
public class DemoJobOptions
{
    public string Url { get; set; }
}
```
Now we populate them as follows:
```
serviceCollection.AddOptions();
serviceCollection.Configure<DemoJobOptions>(options =>
{
    options.Url = connectionSection["Url"];
});
```
And inject them into a constructor. Not that we inject IOptions<T>, not the options instance directly.
```
public DemoJob(IDemoService demoService, IOptions<DemoJobOptions> options)
{
    _demoService = demoService;
    _options = options.Value;
}
```

##Conclusion
In this article, we've seen how we can leverage .NET Core functionality to make our use of Quartz.NET more flexible.