让我们假设我已在应用程序启动时注册了某些服务,并且只想针对单个请求将其替换为另一种实现。 有办法实现吗?
我为什么需要它?因为在某些情况下,我希望某些逻辑继续进行,而数据库中没有该逻辑所需的数据,而是通过在请求中传递该数据并对其进行模拟,因此从数据库获取该数据的服务将返回从请求传递的模拟数据。
答案 0 :(得分:3)
一旦应用程序运行,就无法替换注册。解决此问题的一般方法是使用代理实现,该实现将根据所需条件转发到所需实现。
因此,请考虑以下抽象和实现:
public interface IMyService
{
void DoSomething();
}
public class RealService : IMyService
{
public void DoSomething() { ... }
}
public class AlternativeService : IMyService
{
public void DoSomething() { ... }
}
在这两个实现旁边,您可以创建第三个代理实现:
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";
}
此ProxyService
实现会根据某些条件将所有传入呼叫转发到real或替代实现。在示例中,该条件读取当前请求的用户名,但实际上可以是任何内容。
可以按如下方式注册课程:
services.AddTransient<IMyService, ProxyService>();
services.AddScoped<RealService>();
services.AddScoped<AlternativeService>();
答案 1 :(得分:0)
通用问题是如何替换注册的实现?
我想您会在这里找到答复:Replace service registration in ASP.NET Core built-in DI container?
答案 2 :(得分:-1)
假设您已经注册了接口实现,我的解决方案是拥有2个接口。您可以使用接口继承来管理一致性。
所以你最终会得到类似的东西
interface IDataProvider
{
object GetData();
}
interface IDbDataProvider : IDataProvider
{
}
interface IMockDataProvider : IDataProvider
{
}
class DbDataProvider() : IDbDataProvider
{
object GetData()
{
// Do databasey stuff
}
}
class MockDataProvider() : IMockDataProvider
{
object GetData() => new MockData(); // Or whatever
}
class Normal(IdbDataProvider dataProvider)
{
var data = dataProvider.GetData();
}
class Weird(IMockDataProvider dataProvider)
{
var data = dataProvider.GetData();
}