I want to have multiples implementation of the IUserRepository each implementation will work with a database type either MongoDB or any SQL database. To do this I have ITena
You can try injecting a factory rather than the actual repository. The factory will be responsible for building the correct repository based on the current user identity.
It might require a little more boiler plate code but it can achieve what you want. A little bit of inheritance might even make the controller code simpler.
You should define a proxy implementation for IUserRepository
and hide the actual implementations behind this proxy and at runtime decide which repository to forward the call to. For instance:
public class UserRepositoryDispatcher : IUserRepository
{
private readonly Func<bool> selector;
private readonly IUserRepository trueRepository;
private readonly IUserRepository falseRepository;
public UserRepositoryDispatcher(Func<bool> selector,
IUserRepository trueRepository, IUserRepository falseRepository) {
this.selector = selector;
this.trueRepository = trueRepository;
this.falseRepository = falseRepository;
}
public string Login(string username, string password) {
return this.CurrentRepository.Login(username, password);
}
public string Logoff(Guid id) {
return this.CurrentRepository.Logoff(id);
}
private IRepository CurrentRepository {
get { return selector() ? this.trueRepository : this.falseRepository;
}
}
Using this proxy class you can easily create a runtime predicate that decides which repository to use. For instance:
services.AddTransient<IUserRepository>(c =>
new UserRepositoryDispatcher(
() => c.GetRequiredService<ITenant>().DataBaseName.Contains("Mongo"),
trueRepository: c.GetRequiredService<UserMongoRepository>()
falseRepository: c.GetRequiredService<UserSqlRepository>()));