ASP.NET Core Dependency Injection – How to Register Generic Types Exploring how generic types can be registered with the built-in Microsoft DI container

Since its release, ASP.NET Core has shipped with a “basic” Dependency Injection (DI) container included. This supports the functionality required to run the framework which was built from the ground up to support the use of DI throughout.

The ASP.NET documentation describes some general information about the use of DI in ASP.NET Core.

The documentation for the DI container (ServiceProvider) claims that its quite basic and not a replacement for more fully featured containers such as AutoFac or StructureMap for example. In my experience, for many of my requirements it has proved quite sufficient. In this short post I want to explore a less common registration requirement that may exist for some developers.

Imagine a scenario where you want to register a generic interface and a generic implementation with the ASP.NET Core DI container. In ASP.NET Core itself, an example of this use case is the ILogger<T> interface. We can ask for an ILogger<T> in constructors of our Controllers for example, where T is the Type that the logger will be logging for.

To put this more concretely; if we have a ValuesController and we want to log caught errors from our Actions, we can require an ILogger<ValuesController> in our constructor for the ValuesController. When the controller is constructed by the framework it will receive an implementation of the generic Logger<T> for our provided Type parameter. Under the covers the ILoggerFactory will use the type name to return the appropriate Logger. Messages logged via that logger will then include the full name of the Type (Namespace.ValuesController) when logged to the console for example.

A common way to register services with the ServiceCollection is using the generic extension methods. To add a Singleton registration for an interface and it’s concrete type for example we can call…

serviceCollection.AddSingleton<IService, MyService>();

The signature for the AddSingleton method is…

public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection serviceswhere TService : class where TImplementation : class, Tservice

This works well for most scenarios but doesn’t work if we want to register generic services.

For a slightly contrived example, let’s say we have an interface like this…

And an implementation like this…

We want to be able to ask for an IThing<SomeType> in the constructor of a consumer which will get the correct GenericThing<SomeType> injected.

In this case we can use a different extension method on the ServiceCollection that accepts the types as parameters. Our registration would then look like this…

We now have our generic interface and implementation registered correctly. We can now consume this via DI wherever we need it injected.

Other posts in this series

ASP.NET Core Dependency Injection – Registering Multiple Implementations of an Interface
ASP.NET Core Dependency Injection – Registering Implementations Using Delegates