Let's assume I have some service registered as scoped in the application startup and I want to replace it with another implementation only for single request. Is there a way for achieving that?
Why I need it? because there is a case when I want some logic to proceed without having necessary data for that logic in the database but by passing that data in a request and mocking it, so services which were getting it from database will return mocked data passed from request.
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>();