Сервис не зарегистрирован в сервисе коллекции

0
задан Bercovici Adrian 18 January 2019 в 13:44
поделиться

1 ответ

Я не могу воспроизвести проблему.

GetService вернет ноль, если запрошенная служба не была зарегистрирована. Если был вызван GetRequiredService, он бы выдал исключение.

В этом коде есть две проблемы.

Во-первых, эта строка:

services.AddTransient(y =>wrapper);

регистрирует фабричную функцию , которая возвращает тот же экземпляр HttpWrapper, а не сам экземпляр HttpWrapper. Эта функция вернет все, что содержит wrapper.

Во-вторых, AddTransient говорит, что это временный сервис, и все же один и тот же экземпляр будет возвращаться каждый раз.

Если одна и та же услуга используется каждый раз, при регистрации следует использовать AddSingleton:

services.AddSingleton<HttpWrapper>();

Если каждый раз требуется новый экземпляр , он должен быть :

services.AddTransient<HttpWrapper>();

Тестовый код

Я использовал этот код для проверки проблемы и не могу воспроизвести ее:

static void Main(string[] args)
{
    IServiceCollection services = new ServiceCollection();
    try
    {
        HttpWrapper wrapper = new HttpWrapper();
        services.AddTransient(provider => wrapper);

        ServiceProvider prov = services.BuildServiceProvider();
        HttpWrapper returned = prov.GetRequiredService<HttpWrapper>();

        Console.WriteLine("No problem");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

Класс будет создан без каких-либо проблем. Единственный способ этого потерпеть неудачу - для wrapper быть нулевым. Я использую GetRequiredService, чтобы вызвать исключение, если регистрация не найдена.

Типизированные клиенты Http

Из комментариев выясняется, что проблема real заключается в том, как создать службу, которая правильно использует HttpClient. Повторное использование одного и того же экземпляра улучшит производительность, поскольку оно будет поддерживать существующие TCP-соединения в пуле соединений. Это все еще необходимо периодически перерабатывать, хотя для обработки изменения адресов DNS. Использование временного HttpClient плохо, но так же используется один экземпляр HttpClient.

HttpClientFactory решает обе проблемы, объединяя и перерабатывая экземпляров HttpClientHandler , которые фактически выполняют HTTP-запросы для каждого HttpClient. Статья Использование HttpClientFactory для реализации устойчивых HTTP-запросов объясняет, как это работает, но вкратце, просто добавив:

services.AddHttpClient<ICatalogService, CatalogService>();

Гарантирует, что каждый экземпляр CatalogService будет обрабатываться должным образом HttpClient. Все, что нужно CatalogService, это принять HttpClient в его конструкторе и использовать его в своих методах:

public class CatalogService : ICatalogService
{
    private readonly HttpClient _httpClient;

    public CatalogService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<Catalog> GetCatalogItems(int page, int take, 
                                           int? brand, int? type)
    {
        ....
        var responseString = await _httpClient.GetStringAsync(uri);
        ...
    }
}

Метод расширения AddHttpClient доступен в Microsoft.Extensions.Http package

Адаптируя это к вопросу, HttpWrapper должен принять параметр HttpClient в своем конструкторе:

public class HttpWrapper 
{
    private readonly HttpClient _cl;
    public HttpWrapper(HttpClient client)
    {
        _cl=client;
    }

    public string TestUrl = "aaa";

}

и зарегистрироваться с AddHttpClient:

[117 ]

После этого его можно решить с помощью:

var returned = prov.GetRequiredService<HttpWrapper>();
0
ответ дан Panagiotis Kanavos 18 January 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: