Как правильно зарегистрировать абстрактные, универсальные классы в startup.cs для внедрения зависимостей? - PullRequest
1 голос
/ 07 мая 2019

Я пытаюсь создать сервис MVC, который вызывает 2 разных API - Amazon и Apple.Код выглядит следующим образом:

public abstract class ApiHttpCaller<T>
{
    protected static HttpClient _client;

    protected ApiHttpCaller()
    {

        _client = new HttpClient();
        _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    }

    public abstract Task<T> RetrieveApiResultAsync(string searchValue);
}

Этот ApiHttpCaller реализован с помощью моих двух спецификаций AmazonApiCaller и AppleApiCaller, давайте рассмотрим только одну из них:

public class AmazonApiCaller : ApiHttpCaller<AmazonResponseModel>
{
    protected static IOptions<ApiUrls> _apiUrls;

    public AmazonApiCaller(IOptions<ApiUrls> apiUrls)
    {
        _apiUrls = apiUrls;
    }

    public override async Task<AmazonResponseModel> RetrieveApiResultAsync(string searchValue)
    {            
        ..logic to call the api..
        string responseBody = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<AmazonResponseModel>(responseBody);
    }
}

, как вы можете видеть,поправьте меня, если архитектура неверна, здесь в качестве обобщений используется AmazonResponseModel .Как вы можете себе представить, AmazonApi и AppleApi возвращают 2 разные модели.Вот почему мой абстрактный родительский класс ApiHttpCaller использует обобщенные значения T , которые в спецификации AmazonApiCaller становятся AmazonResponseModel .Такие API вызываются из моего контроллера.

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

    [HttpPost]
    public async Task<ActionResult> Post([FromBody] string value)
    {
        var amazonCaller = _apiCallers.First(x => x.GetType() == typeof(AmazonApiCaller));
        var itemResult = await amazonCaller.RetrieveApiResultAsync(value);
        ..more logic to map the itemResult to a viewModel..
    }
}

Итак, первый вопрос: считаете ли вы правильным использование genercis T в контроллере, который затем становится специфическим типом внутри каждогоapi caller?

Второе и более важное: я не знаю, как зарегистрировать в Startup.cs ApiHttpCallers таким образом, чтобы они правильно вводились в мой контроллер.Первое предположение таково:

services.AddSingleton<ApiCaller<T>, AmazonApiCaller<AmazonResponseModel>>();
services.AddSingleton<ApiCaller<T>, AppleApiCaller<AppleResponseModel>>(); 

Дело в том, что Startup.cs ничего не знает о T .

Ответы [ 2 ]

1 голос
/ 07 мая 2019

служб для регистрации:

services.AddSingleton<ApiCaller<AmazonResponseModel>, AmazonApiCaller>();
services.AddSingleton<ApiCaller<AppleResponseModel>, AppleApiCaller>(); 
services.AddTransient(typeof(ItemsController<>));

Измените контроллер следующим образом:

public class ItemsController<T> : ControllerBase
{
    private readonly ApiHttpCaller<T> _apiCaller;
    public ItemsController(ApiHttpCaller<T> apicaller){
        _apiCaller = apicaller;
    }

    [HttpPost]
    public async Task<ActionResult> Post([FromBody] string value)
    {
        // do something with the requested API Caller
    }
}

Теперь это должно ввести правильный ApiCaller в вашу службу.Конечно, вам нужно указать тип при введении ItemsController:

// Constructor
public AnyClass(ItemsController<AmazonResponseModel> controller){
    // _apiCaller of controller will be AmazonApiCaller
}

или, возможно, использовать другой IoC Container, такой как ninject .

Youмогли бы воспользоваться такими функциями, как контекстные и именованные привязки, которые описаны на их странице.

0 голосов
/ 07 мая 2019

Ваша регистрация здесь неверна.Это должно быть так:

services.AddSingleton<ApiCaller<AmazonResponseModel>, AmazonApiCaller>();
 services.AddSingleton<ApiCaller<AppleResponseModel>, AppleApiCaller>();

вам нужно указать, какой универсальный вариант будет соответствовать какой реализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...