Part 2 – ASP.NET Core Dependency Injection

In this article, we will examine some of ASP.NET Core DI features with doing examples. Because, some of these features are more important to understand how this features are used in framework. Also, if we know this features, we can design our project with better design. Let’s start to examples.

Factory Method

First, I will create objects to test.

public class MyService
{
    private readonly IMyServiceDependency _dependency;
 
    public MyService(IMyServiceDependency dependency)
    {
        _dependency = dependency;
    }
 
    public void DoIt()
    {
        _dependency.DoIt();
    }
}
 
public class MyServiceDependency : IMyServiceDependency
{
    public void DoIt()
    {
        Console.WriteLine("Hello from MyServiceDependency");
    }
}
 
public interface IMyServiceDependency
{
    void DoIt();
}

And I am registering the objects for DI.

static void Main(string[] args)
{
    FactoryMethodDemo();
}
 
public static void FactoryMethodDemo()
{
    IServiceCollection services = new ServiceCollection();
 
    services.AddTransient<IMyServiceDependencyMyServiceDependency>();
    // Overload method for factory registration
    services.AddTransient(
        provider => new MyService(provider.GetService<IMyServiceDependency>())
    );
 
    var serviceProvider = services.BuildServiceProvider();
    var instance = serviceProvider.GetService<MyService>();
 
    instance.DoIt();
}

In second registration, I used factory overload method for register service and result.

FactoryDemo

Instance Registration

You can create an object instance before registering it.  Object for instance registration.

public class MyInstance
{
    public int Value { getset; }
}

And demo:

static void Main(string[] args)
{
    InstanceRegistrationDemo();
}
 
public static void InstanceRegistrationDemo()
{
    var instance = new MyInstance { Value = 44 };
 
    IServiceCollection services = new ServiceCollection();
 
    services.AddSingleton(instance);
 
    foreach (ServiceDescriptor service in services)
    {
        if (service.ServiceType == typeof(MyInstance))
        {
            var registeredInstance = (MyInstance)service.ImplementationInstance;
 
            Console.WriteLine("Registered instance : " + registeredInstance.Value);
        }
    }
 
    var serviceProvider = services.BuildServiceProvider();
    var myInstance = serviceProvider.GetService<MyInstance>();
 
    Console.WriteLine("Registered service by instance registration : " + myInstance.Value);
}

First, I created a new object before registering it’s type in DI. Then I resolved the registered instance by using both service.Implementation and serviceProvider.GetInstance methods. And the result:

InstanceRegistration

Generic Type Registration

I think, this is one of the best features. Suppose we have a generic repository. If we want to register this repository for all types for DI, We should register all types separately like Repo, Repo, etc… But now, ASP.NET Core DI support generic registration. And its easy to register and resolve.

IServiceCollection services = new ServiceCollection();
 
services.AddTransient<MyClassWithValue>();
services.AddTransient(typeof(IMyGeneric<>), typeof(MyGeneric<>));
 
var serviceProvider = services.BuildServiceProvider();
 
var service = serviceProvider.GetService<IMyGeneric<MyClassWithValue>>();

Multiple Registration

ASP.NET Core DI supports multiple registration with different options. This feature gives us some flexibility. Let’s do example to understand better. I am defining objects to test this feature.

public interface IHasValue
{
    object Value { getset; }
}
 
public class MyClassWithValue : IHasValue
{
    public object Value { getset; }
 
    public MyClassWithValue()
    {
        Value = 42;
    }
}
 
public class MyClassWithValue2 : IHasValue
{
    public object Value { getset; }
 
    public MyClassWithValue2()
    {
        Value = 43;
    }
}

I will show different usage of multiple registration feature with example.

static void Main(string[] args)
{
    MultipleImplementation();
    MultipleImplementationWithTry();
    MultipleImplementationWithReplace();
}
 
private static void MultipleImplementation()
{
    IServiceCollection services = new ServiceCollection();
 
    services.AddTransient<IHasValueMyClassWithValue>();
    services.AddTransient<IHasValueMyClassWithValue2>();
 
    var serviceProvider = services.BuildServiceProvider();
    var myServices = serviceProvider.GetServices<IHasValue>().ToList();
    var myService = serviceProvider.GetService<IHasValue>();
 
    Console.WriteLine("----- Multiple Implemantation Services -----------");
 
    foreach (var service in myServices)
    {
        Console.WriteLine(service.Value); 
    }
 
    Console.WriteLine("----- Multiple Implemantation Service ------------");
    Console.WriteLine(myService.Value);
}
 
private static void MultipleImplementationWithTry()
{
    IServiceCollection services = new ServiceCollection();
 
    services.AddTransient<IHasValueMyClassWithValue>();
    services.TryAddTransient<IHasValueMyClassWithValue2>();
 
    var serviceProvider = services.BuildServiceProvider();
    var myServices = serviceProvider.GetServices<IHasValue>().ToList();
 
    Console.WriteLine("----- Multiple Implemantation Try ----------------");
 
    foreach (var service in myServices)
    {
        Console.WriteLine(service.Value);
    }
}
 
private static void MultipleImplementationWithReplace()
{
    IServiceCollection services = new ServiceCollection();
 
    services.AddTransient<IHasValueMyClassWithValue>();
    services.Replace(ServiceDescriptor.Transient<IHasValueMyClassWithValue2>());
 
    var serviceProvider = services.BuildServiceProvider();
    var myServices = serviceProvider.GetServices<IHasValue>().ToList();
 
    Console.WriteLine("----- Multiple Implemantation Replace ------------");
 
    foreach (var service in myServices)
    {
        Console.WriteLine(service.Value);
    }
 
    Console.WriteLine("--------------------------------------------------");
}

First demo of above code, I added IHasValue object twice with different types. And when I want to get service, It gives me the last registered service.

Second demo, if I use TryAdd- method, it is not registered if there is a registered service.

And last one, I can replace registered service with another. You can understand better when you see the result.

MultipleRegistration

In this part, I tried to explain DI in ASP.NET Core most used features.

In next last part, I will explain DI options, how to use ASP.NET Core DI with autofac and castle windsor.

Source code: ASP.NET Core Dependency Injection Training

#net-core, #asp-net-core, #dependency-injection