将依赖注入应用于抽象类 c# 的不同实现

Tar*_*rta 2 c# api model-view-controller dependency-injection asp.net-core

当我可以在我的控制器中注入抽象类的 2 个不同实现时,我想在我的 .net 核心应用程序中构建一个 MVC 场景。这些实现调用它们的外部相关 API。也许架构是错误的,因此我向您征求建议,但请先按照我的想法进行操作。我创建了一个通用抽象类。为什么要抽象?因为调用 API 的基本方式/属性对每个人都是一样的。就我而言,到目前为止我只有一个 HttpClient。

public abstract class ApiCaller
{
    protected static HttpClient client;
    protected static string ApiUrl;

    public ApiCaller(string apiUrl)
    {
        client = new HttpClient();
        ApiUrl = apiUrl;
    }

    public abstract string GetApiResultAsync();
}
Run Code Online (Sandbox Code Playgroud)

之后,我将拥有两个不同的类Api1ServiceApi2Service,它们扩展了ApiCaller,并且将有自己不同的调用相关 API 的方式。

public class Api1Service : ApiCaller
{
    public Api1Service(string apiUrl) : base(apiUrl)
    {

    }

    public override string GetApiResultAsync()
    {
        ...
    }
}


public class Api2Service : ApiCaller
{
    public Api2Service(string apiUrl) : base(apiUrl)
    {

    }

    public override string GetApiResultAsync()
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,在我的控制器中,我想注入两个实例,因为我想使用这两个业务服务..但我不知道这是否可能。

[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    private readonly ApiCaller _apiCaller;

    public BooksAndAlbumsController(ApiCaller apiCaller)
    {
        _apiCaller = apiCaller;
    }

    [HttpPost]
    public void Post([FromBody] string value)
    {
        _apiCaller.GetApiResultAsync() //but I want to use both my apiCallers
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,不知何故,在我的容器中,我需要注册我的抽象类的两个实现。我怎样才能做到这一点?如果您发现我的架构中存在缺陷,请告诉我!

JOS*_*Ftw 5

您可以注入一个IEnumerable<ApiCaller>然后同时使用它们。

在容器中注册两个 ApiCallers,然后将 注入到IEnumerable<ApiCaller>您的控制器中。

像这样的东西:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<ApiCaller, Api1Service>();
    services.AddSingleton<ApiCaller, Api2Service>();
}
Run Code Online (Sandbox Code Playgroud)

我的控制器

[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    private readonly IEnumerable<ApiCaller> _apiCallers;

    public MyController(IEnumerable<ApiCaller> apiCallers)
    {
        _apiCallers = apiCallers;
    }

    [HttpPost]
    public async Task Post([FromBody] string value)
    {
        // Loop through one by one or call them in parallel, up to you.
        foreach(var apiCaller in _apiCallers)
        {
            var result = await apiCaller.GetApiResultAsync();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种可能是注册 Api1Service 和 Api2Service,然后像这样注入它们。不过,它不会像第一个解决方案那样动态/灵活。

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<Api1Service>();
    services.AddSingleton<Api2Service>();
}
Run Code Online (Sandbox Code Playgroud)

我的控制器

[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    private readonly Api1Service _api1Service;
    private readonly Api2Service _api2Service;

    public MyController(Api1Service api1Service, Api2Service api2Service)
    {
        _api1Service = api1Service;
        _api2Service = api2Service;
    }

    [HttpPost]
    public async Task Post([FromBody] string value)
    {
        var result1 = await apiService1.GetApiResultAsync();
        var result2 = await apiService2.GetApiResultAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)