Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to prevent injecting a single implementation of an interface that was registered multiple times in ASP.NET?

In my code, there is the registration of two different services with the same interface as this:

services.AddSingleton<IServiceResolver, ServiceResolver>();
services.AddSingleton<IService, ServiceA>();
services.AddSingleton<IService, ServiceB>();

The ServiceResolver is used to pick the correct service based on some circumstances. The ServiceResolver itself has a constructor like this:

public ServiceResolver(IEnumerable<IService> idServices, ...)

So, any business logic related code should always use the service resolver to pick the correct service to use.

The Problem:

IService can be injected directly into business code and will then be always ServiceB since this was the last IService registered.

Is there a way to prevent injecting a single implementation of an interface that was registered multiple times?

I know that as long as you stick to just injecting IServiceResolver there will be no problem, but the code would be much safer to use if this simple thing could be prevented somehow.

like image 354
Philip Claren Avatar asked Dec 21 '25 17:12

Philip Claren


1 Answers

There may be a way to do this if no other classes need to resolve any of the IServices. You can set up ServiceResolver so that it has knowledge about what IService types exist and then internally it can manually create all the instances using the existing ServiceCollection. To do this, ServiceResolver will need IServiceProvider and you do lose some functionality, like having scope handled automatically for you.

Here's a quick example of what I mean.

The new ServiceResolver class:

public class ServiceResolver : IServiceResolver
{
    public static void Register<TService>() where TService : IService
    {
        ServiceTypes.Add(typeof(TService));
    }
    
    public ServiceResolver(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }
    
    private IEnumerable<IService> GetServices()
    {
        return ServiceTypes.Select(t => ActivatorUtilities.CreateInstance(_serviceProvider, t) as IService);
    }
    
    private static List<Type> ServiceTypes = new List<Type>();
    private readonly IServiceProvider _serviceProvider;
}

Registering types:

ServiceResolver.Register<ServiceA>();
ServiceResolver.Register<ServiceB>();

services.AddSingleton<IServiceResolver, ServiceResolver>();

I created a working example of this here

A modified version where the IServices are created as singletons here

like image 164
amura.cxg Avatar answered Dec 23 '25 06:12

amura.cxg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!