IoC - Multiple implementations support for a single interface

Viewed 12385

I am wondering why .Net IoC containers do not easily support multiple implementations for a single interface! May be I am wrong, but as far I have seen, frameworks like Ninject partially supports this feature using annotations (how?). I do not think other frameworks like Windsor or simple injector have an easy mechanism to support this scenario.

Is there any reason why this is not supported by many frameworks? AFAIK, one of the most important reasons to use interfaces is to achieve loose coupling. If the frameworks designed to improve loose coupling, do not fluently support multiple implementations for a single interface, I do not understand why!

P.S. Of course I understand that there will be a resolution issue during run time, and the container would be confused which implementation to choose, but that is something which has to be considered in the design, right?

7 Answers

If you want to access implementations with certain conditions, you can use Dictionary.

UC_Login: The user must validate their credentials according to the Authentication Mode (By Database or Active Directory), each authentication mode has different business logic.

My code: I have an Interface called IAuthService.cs I have two classes called DatabaseAuthService.cs and ActiveDirectoryAuthService.cs both with the same IsValidCredential (User user) method that depend on the same Interface.

public interface IAuthService
{
  Task<bool> IsValidCredentialAsync(User user);
}

public class DatabaseAuthService : IAuthService
{
  private readonly IDatabaseAuthRepository _databaseAuthRepository;
  // User IServiceProvider for access to any other interfaces
  // using Microsoft.Extensions.DependencyInjection; using System;
  public DatabaseAuthService(IServiceProvider serviceProvider)
  => _databaseAuthRepository = serviceProvider.GetService<IDatabaseAuthRepository>();

  public async Task<bool> IsValidCredentialAsync(User user)
  {
    // return await _databaseAuthRepository.something...
  }
}

public class LdapAuthService : IAuthService
{
  public LdapAuthService()
  {
  }
  public async Task<bool> IsValidCredentialAsync(User user)
  {
    // something...
  }
}

Condition Implemented: I use the AuthenticationAppServiceclass, with the LoginAsync (LoginDto dto) method.

public class AuthenticationAppService
{
  private readonly Dictionary<AuthenticationModeEnum, IAuthService> _authProviders =
      new Dictionary<AuthenticationModeEnum, IAuthService>();
  public AuthenticationAppService(IServiceProvider serviceProvider)
  {
    _authProviders.Add(AuthenticationModeEnum.Database, new DatabaseAuthService(serviceProvider));
    _authProviders.Add(AuthenticationModeEnum.ActiveDirectory, new LdapAuthService());
  }

  public Task<bool> LoginAsync(LoginDto dto)
  {
    var user = Mapper.Map<user, LoginDto>(dto);
    return await _authProviders[(AuthenticationModeEnum)dto.AuthMode].IsValidCredentialAsync(user);
  }
}

maybe not on topic, but hope it helps.

Related