OdeToCode IC Logo

ASP.NET Core Dependency Injection Understands Unbound Generics

Friday, April 21, 2017

Continuing with topics based on ASP.NET Core code reviews.

Here is a bit of code I came across in an application’s Startup class.

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IStore<User>, SqlStore<User>>();
    services.AddScoped<IStore<Invoice>, SqlStore<Invoice>>();
    services.AddScoped<IStore<Payment>, SqlStore<Payment>>();
    // ...
}

The actual code ran for many more lines, with the general idea that the application needs an IStore implementation for a number of distinguished objects in the system.

Because ASP.NET Core understands unbound generics, there is only one line of code required.

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped(typeof(IStore<>), typeof(SqlStore<>));
}

Unbound generics are not useful in day to day business programming, but if you are curious how the process works, I did show how to use unbound generics at a low level in my C# Generics course.

One downside to this approach is the fact that you might experience a runtime error (instead of a compile error) if a component requests an implementation of IStore<T> that isn’t possible. For example, if a concrete implementation of IStore<T> uses a generic constraint of class, then the following would happen:

Assert.Throws<ArgumentException>(() =>
{
    services.GetRequiredService<IStore<int>>();
});

However, this problem should be avoidable.