Я не могу воспроизвести проблему.
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);
}
}
Класс будет создан без проблем. Единственный способ этого не сделать - 1036 * быть нулевым. Я использую 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
Адаптируя это к вопросу, HttpWrapper
должен принять параметр HttpClient в своем конструкторе:
public class HttpWrapper
{
private readonly HttpClient _cl;
public HttpWrapper(HttpClient client)
{
_cl=client;
}
public string TestUrl = "aaa";
}
И зарегистрируйтесь с AddHttpClient
:
services.AddHttpClient<HttpWrapper>();
После этого его можно решить с помощью:
var returned = prov.GetRequiredService<HttpWrapper>();