Once the application is running, it is impossible to replace registration. The general solution to this problem is to use a proxy implementation that forwards to the desired implementation based on the required conditions.
So consider the following abstraction and implementations:
public interface IMyService
{
void DoSomething();
}
public class RealService : IMyService
{
public void DoSomething() { ... }
}
public class AlternativeService : IMyService
{
public void DoSomething() { ... }
}
Next to these 2 implementations, you can create a third, proxy implementation:
public class ProxyService : IMyService
{
private readonly RealService real;
private readonly AlternativeService alternative;
private readonly IHttpContextAccessor accessor;
public ProxyService(
RealService real,
AlternativeService alternative,
IHttpContextAccessor accessor)
{
this.real = real;
this.alternative = alternative;
this.accessor = accessor;
}
public void DoSomething() => this.Service.DoSomething();
private IMyService Service => this.UseRealThing ? this.real : this.alternative.
private bool UseRealThing => this.accessor.HttpContext.User.Name != "Artem";
}
This ProxyService
implementation forwards any incoming call to either the real or the alternative implementation, based on some condition. In the example, that condition reads the user name of the current request, but it could in fact be anything.
The classes can be registered as follows:
services.AddTransient<IMyService, ProxyService>();
services.AddScoped<RealService>();
services.AddScoped<AlternativeService>();