Part 3 – ASP.NET Core Dependency Injection

Options

There is a pattern that uses custom options classes to represent a group of related settings. As usual, I will explain it with example. First, download Microsoft.Extensions.Options.dll from nuget.

public class MyTaxCalculator
{
    private readonly MyTaxCalculatorOptions _options;
 
    public MyTaxCalculator(IOptions<MyTaxCalculatorOptions> options)
    {
        _options = options.Value;
    }
 
    public int Calculate(int amount)
    {
        return amount * _options.TaxRatio / 100;
    }
}
 
public class MyTaxCalculatorOptions
{
    public int TaxRatio { getset; }
 
    public MyTaxCalculatorOptions()
    {
        TaxRatio = 118;
    }
}

I created a class to calculate tax that uses an option class to get information how to calculate tax. I injected this option as IOption generic type.  And here is the usage;

static void Main(string[] args)
{
    ServiceOptionsDemo1();
}
 
private static void ServiceOptionsDemo1()
{
    IServiceCollection services = new ServiceCollection();
 
    services.AddOptions();
    services.AddTransient<MyTaxCalculator>();
    services.Configure<MyTaxCalculatorOptions>(options =>
    {
        options.TaxRatio = 135;
    });
 
    var serviceProvider = services.BuildServiceProvider();
    var calculator = serviceProvider.GetService<MyTaxCalculator>();
 
    Console.WriteLine(calculator.Calculate(100));
}

IServiceCollection has an extension method that named Configure. With using this method, we can define/change option values at compile time. When I run the code, here is the result.

options_demo_1

In this example, we can set and use options in DI with adding values hardcoded. Of course we can read option values from an file like json. Let’s do an example for this.

Configurations

The configuration API provides a way of configuring that can be read at runtime from multiple resources. These resources can be file (.ini, .json, .xml, …), cmd arguments, environment variables, in-memory objects, etc…

First, you should download Microsoft.Extensions.Options.ConfigurationExtensions.dll and Microsoft.Extensions.Configuration.Json.dll and I will add an appsettings.json to my project.

{
  "TaxOptions": {
    "TaxRatio""130"
  }
}

And I am modifying the demo like following.

static void Main(string[] args)
{
    ServiceOptionsDemo2();
}
 
private static void ServiceOptionsDemo2()
{
    var configuration = new ConfigurationBuilder()
        .AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json"))
        .Build();
 
    IServiceCollection services = new ServiceCollection();
 
    services.AddOptions();
    services.AddScoped<MyTaxCalculator>();
 
    services.Configure<MyTaxCalculatorOptions>(configuration.GetSection("TaxOptions"));
 
    var serviceProvider = services.BuildServiceProvider();
 
    var calculator = serviceProvider.GetRequiredService<MyTaxCalculator>();
    Console.WriteLine(calculator.Calculate(200));
}

I added ConfigurationBuilder to read options from json file. In json file, data structure is matching with configuration.GetSection(“TaxOptions”). And result is:

options_demo_2

Using Castle Windsor and Autofac

Using another DI container is very easy. Just we are adding the nuget package and create an instance of container.

Castle Windsor

First, I am adding Castle.Windsor.MsDependencyInjection from nuget. And usage;

IServiceCollection services = new ServiceCollection();
services.AddTransient<MyService>();
 
var windsorContainer = new WindsorContainer();
 
windsorContainer.Register(
    Component.For<MyService>()
);
 
var serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(
    windsorContainer,
    services
);
 
var myService = serviceProvider.GetService<MyService>();

Autofac

For using autofac, you should add the Autofac.Extensions.DependencyInjection nuget package to your project. And usage;

IServiceCollection services = new ServiceCollection();
services.AddTransient<MyService>();
 
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<MyService>();
containerBuilder.Populate(services);
 
var container = containerBuilder.Build();
var serviceProvider = new AutofacServiceProvider(container);
var myService = serviceProvider.GetService<MyService>();

As you can see, after adding nuget packages, you can use them just using their own service provider or service register.

If you investigate source code of the example project, you can understand better.

Source code: ASP.NET Core Dependency Injection Training

#net-core, #asp-net-core, #autofac, #castle-windsor, #dependency-injection, #service-collection, #service-provider