Change injected object at runtime

后端 未结 2 677
一整个雨季
一整个雨季 2020-12-09 12:40

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

相关标签:
2条回答
  • 2020-12-09 13:18

    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.

    0 讨论(0)
  • 2020-12-09 13:32

    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>()));
    
    0 讨论(0)
提交回复
热议问题