DEV Community

Dennis Tretyakov
Dennis Tretyakov

Posted on • Originally published at dennistretyakov.com

One instance for various service types in Microsoft Extensions DI

Recently moving away from Autofac to Microsoft Extensions DI I've faced a problem
that there is no API to register one service implementation instance (singleton, scoped) for various service types.

Autofac behaviour

[Fact]
public void Autofac_ReturnsSameInstance()
{
    var contaienrBuilder = new ContainerBuilder();
    contaienrBuilder.RegisterType<Service>()
        .AsSelf()
        .AsImplementedInterfaces()
        .SingleInstance();

    var container = contaienrBuilder.Build();

    var byInterface = container.Resolve<IService>();
    var byExactType = container.Resolve<Service>();

    Assert.Same(byInterface, byExactType);
}
Enter fullscreen mode Exit fullscreen mode

Microsoft DI behaviour

[Fact]
public void DI_ReturnsDifferentInstances()
{
    var serviceProvider = new ServiceCollection()
        .AddSingleton<Service>()
        .AddSingleton<IService, Service>()
        .BuildServiceProvider();

    var byInterface = serviceProvider.GetRequiredService<IService>();
    var byExactType = serviceProvider.GetRequiredService<Service>();

    Assert.NotSame(byInterface, byExactType);
}
Enter fullscreen mode Exit fullscreen mode

Achieving similar behaviour on Microsoft DI

Autofac allows multiple keys for the same implementation.
Microsoft DI is one to one map.
To achieve the same behaviour choose the type you will use as the primary key (Service in the example below).
For all other types (like IService in the example below) register resolvers that would resolve a service using primary key.

[Fact]
public void DI_ReturnsSameInstace_LikeAutofac()
{
    var serviceProvider = new ServiceCollection()
        .AddSingleton<Service>()
        .AddSingleton<IService>(sp => sp.GetRequiredService<Service>())
        .BuildServiceProvider();

    var byInterface = serviceProvider.GetRequiredService<IService>();
    var byExactType = serviceProvider.GetRequiredService<Service>();

    Assert.Same(byInterface, byExactType);
}
Enter fullscreen mode Exit fullscreen mode

Code on GitHub.

Top comments (0)