|Interested in Dependency Injection? You may want to check out my Pluralsight course – Dependency Injection in ASP.NET Core.|
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 it’s 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 instance, 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 framework constructs the controller 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 its concrete type, for example, we can call…
The signature for the AddSingleton method is…
public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection services
where 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
|If you found this post useful, you may want to check out my Pluralsight course – Dependency Injection in ASP.NET Core.|