Josh
Josh

Reputation: 8477

.NET Core IServiceCollection Replace not refreshing

I have an Address object that depends on an IState object inject in the constructor:

public class AddressService : BaseService, IAddressService
{
        private readonly IStateRepository _stateRepository;
        private readonly ICacheClass _cache;
        private readonly ILogger<AddressService> _logger;

        public const string StatesCacheKey = "StateListManagedByStateService";

        public AddressService(IStateRepository stateRepository, 
                              ICacheClass cache, 
                              ILogger<AddressService> logger, 
                              IUserContext userContext) : base(userContext)
        {
            _stateRepository = stateRepository;
            _cache = cache;
            _logger = logger;
        }

        public async Task<IReadOnlyList<T>> GetAllStatesAsync<T>() where T : IState
        {
            var list = await _cache.GetAsync<IReadOnlyList<T>>(StatesCacheKey);

            if (list != null) return list;

            var repoList = _stateRepository.GetAll().Cast<T>().ToList();

            _logger.LogInformation("GetAllStates retrieved from repository, not in cache.");

            await _cache.SetAsync(StatesCacheKey, repoList);

            return repoList;
        }
}

IStateRepository is injected by the ASP.NET Core web project with the folling lines in Startup:

    services.AddTransient<IStateRepository, Local.StateRepository>();
    services.AddTransient<IAddressService, AddressService>();

In my Controller I have two action methods. Depending on the one called, I want to change the IStateRepository object associated with DI:

    private readonly IAddressService _addressService;


    public HomeController(IConfiguration configuration, ILogger<HomeController> logger, IAddressService addressService) : base(configuration,logger)
            {
                _addressService = addressService;
            }

    public async Task<IActionResult> DistributedCacheAsync()
    {
                    var services = new ServiceCollection();
                    services.Replace(ServiceDescriptor.Transient<IStateRepository, Repositories.Local.StateRepository>());

                    ViewBag.StateList = await _addressService.GetAllStatesAsync<State>();

                    return View();
    }

    public async Task<IActionResult> DapperAsync()
    {
                    var services = new ServiceCollection();
                    services.Replace(ServiceDescriptor.Transient<IStateRepository, Repositories.Dapper.StateRepository>());

                    ViewBag.StateList = await _addressService.GetAllStatesAsync<State>();

                    return View();
}

The problem is that _addressService already has the Local.StateRepository associated from Startup, and updating it in DapperAsync using Replace doesn't have an effect on it.

How would be able to change IStateRepository in DI during runtime in the example above?

Upvotes: 1

Views: 1376

Answers (1)

Eilon
Eilon

Reputation: 25704

Changing services at runtime is not supported by Microsoft.Extensions.DependencyInjection.

I recommend creating a wrapper service that at runtime can choose between different implementations based on a condition.

Upvotes: 2

Related Questions