ASP.NET Core模拟服务仅在一个请求的范围内

时间:2020-06-05 08:36:04

标签: c# asp.net-core dependency-injection mocking service-provider

让我们假设我已在应用程序启动时注册了某些服务,并且只想针对单个请求将其替换为另一种实现。 有办法实现吗?

我为什么需要它?因为在某些情况下,我希望某些逻辑继续进行,而数据库中没有该逻辑所需的数据,而是通过在请求中传递该数据并对其进行模拟,因此从数据库获取该数据的服务将返回从请求传递的模拟数据。

3 个答案:

答案 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();
}