.NET Core Dependency Injection with Options

With a service that should be injected via dependency injection, but needs some configuration, .NET Core offers a mechanism to supply the configuration values. You don’t need to think about a mechanism how to implement it on your own, but can use the features offered from .NET Core.
In a previous blog post I showed the new .NET Core dependency injection framework Microsoft.Extensions.DependencyInjection. This blog post gives information how services registered with this framework can be configured – using Microsoft.Extensions.Options.

See the new version of this article: It’s all in the Host Class – Dependency Injection with .NET

Injection

The sample code is based on a previous blog post Dependency Injection with .NET Core, so it’s best to read this first.

Using IOptions with the constructor of the Service

The GreetingService service from the previous sample is changed with a constructor receiving options. The IOptions interface is defined in the NuGet package Microsoft.Extensions.Options and gives a standard mechanism for initialization. The IOptions interface receives the generic parameter type GreetingServiceOptions that allows configure all the different options needed by the GreetingService. This type needs to be a class and requires a default constructor as defined by the generic constraints specified with the IOptions interface.

public class GreetingService : IGreetingService
{
    public GreetingService(IOptions<GreetingServiceOptions> options) =>
        _from = options.Value.From;

    private string _from;

    public string Greeting(string name)
    {
        if (name == null) throw new ArgumentNullException(nameof(name));

        return $"Hello, {name}, greetings from {_from}";
    }

Definition of the Options

The GreetingServiceOptions is – as required by the IOptions interface – a class with a default constructor. This class defines the From property that is used by the implementation of the GreetingService.

public class GreetingServiceOptions
{
    public string From { get; set; }
}

Using the Service

Using the service, nothing changed from the previous example. The HelloController receives the IGreetingService via dependency injection, and invokes the Greeting method when the Action method of the controller is invoked.

public class HelloController
{
    private readonly IGreetingService _greetingService;

    public HelloController(IGreetingService greetingService) =>
        _greetingService = greetingService;

    public string Action(string name) =>
        _greetingService.Greeting(name);
}

Making it easier to register the service with the dependency injection container

To make it easier to register the service with the dependency injection container, the extension method AddGreetingService which extends the interface IServiceCollection is defined. To supply the required configuration with the extension method, a parameter Action is added. This parameter is then passed to the Configure extension method of the IServiceCollection interface. This method is defined in the NuGet package Microsoft.Extensions.Options.

public static class GreetingServiceCollectionExtensions
{
    public static IServiceCollection AddGreetingService(this IServiceCollection collection,   
        Action<GreetingServiceOptions> setupAction)
    {
        if (collection == null) throw new ArgumentNullException(nameof(collection));
        if (setupAction == null) throw new ArgumentNullException(nameof(setupAction));

        collection.Configure(setupAction);
        return collection.AddTransient<IGreetingService, GreetingService>();
    }
}

The sample code requires the configuration via the setupAction parameter, that’s why it’s not allowed to pass null which is verified. In case the configuration is optional, it is common with .NET Core to define the setupAction parameter as optional with a default value null.

Building the Dependency Injection Container

What’s left is building the IServiceProvider. With the ServiceCollection, the the AddOptions extension method from Microsoft.Extensions.Options is invoked to add the IOptions interface to the dependency injection container. This interface is needed to resolve the constructor parameter of the service. The implementation of the AddOptions method registers the OptionsManager as a singleton to be resolved for the IOptions interface. After registering the HelloController, the extension method AddGreetingService is used, and with the Action parameter, the service is configured.

private static void RegisterServicesWithOptions()
{
    var services = new ServiceCollection();
    services.AddOptions();
    services.AddTransient<HelloController>();
    services.AddGreetingService(options =>
    {
        options.From = "Christian";
    });

    Container = services.BuildServiceProvider();
}

public static IServiceProvider Container { get; private set; }

Packages needed

To use .NET Core dependency injection with options, these two packages are needed:

  • Microsoft.Extensions.DependencyInjection – this is the package for the core dependency injection features, such as the ServiceCollection class
  • Microsoft.Extensions.Options – this package contains the IOptions interface, the OptionsManager for instantiating the options, as well as the extension methods AddOptions and Configure

Using the Service

The service can now be used in the same way as in the sample of the previous blog post. The configuration is defined for the dependency injection container, and thus the container knows how it can be instantiated.

private static void UseServices()
{
  var controller = Container.GetService<HelloController>();

  string greeting = controller.Action("Stephanie");

  WriteLine(greeting);
}

Summary

Microsoft.Extensions.DependencyInjection is a new dependency injection framework with .NET Core. It is used with ASP.NET Core applications, but can be used with other technologies such as UWP and WPF as well. With the interface IOptions from Microsoft.Extensions.Options, a standard mechanism is available to configure services.

Sample code for this article is available with the More Samples. My new book Professional C# 7 and .NET Core 2.0 has a complete chapter dedicated to dependency injection, and DI is used with many chapters in this book.

Have fun with programming and learning!
Christian

More Information

More information about the .NET Core dependency injection framework is available in my new book and my workshops.

Professional C# 7 and .NET Core 2.0
Trainings
Dependency Injection with .NET Core

Image Dependency Injection © Madartists | Dreamstime.com Doctor With Syringe Needle

8 thoughts on “.NET Core Dependency Injection with Options

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.