Можно ли внедрить IHttpClientFactory в строго типизированный клиент? - PullRequest
3 голосов
/ 24 июня 2019

Как говорит заголовок.

Допустим, я зарегистрировал строго типизированного клиента, например

var services = new ServiceCollection();

//A named client is another option that could be tried since MSDN documentation shows that being used when IHttpClientFactory is injected.
//However, it appears it gives the same exception.
//services.AddHttpClient("test", httpClient => 
services.AddHttpClient<TestClient>(httpClient =>
{
    httpClient.BaseAddress = new Uri("");                    
});
.AddHttpMessageHandler(_ => new TestMessageHandler());

//Registering IHttpClientFactory isn't needed, hence commented.
//services.AddSingleton(sp => sp.GetRequiredService<IHttpClientFactory>());
var servicesProvider = services.BuildServiceProvider(validateScopes: true);

public class TestClient
{
    private IHttpClientFactory ClientFactory { get; }
    public TestClient(IHttpClientFactory clientFactory)
    {
        ClientFactory = clientFactory;
    }

    public async Task<HttpResponseMessage> CallAsync(CancellationToken cancellation = default)
    {
        //using(var client = ClientFactory.CreateClient("test")) 
        using(var client = ClientFactory.CreateClient())
        {
            return await client.GetAsync("/", cancellation);
        }
    }
}

// This throws with "Message: System.InvalidOperationException : A suitable constructor
// for type 'Test.TestClient' could not be located. Ensure the type is concrete and services
// are registered for all parameters of a public constructor.

var client = servicesProvider.GetService<TestClient>();

Но, как отмечено в комментариях, будет выдано исключение.Я скучаю по чему-то весёлому или такая договорённость невозможна?

1 Ответ

2 голосов
/ 25 июня 2019

Пожалуйста, прочитайте о Типизированные клиенты :

Типизированный клиент принимает параметр HttpClient в своем конструкторе

вместо IHttpClientFactory вашего классадолжен принять HttpClient в своем конструкторе, который будет предоставлен DI (включается с расширением AddHttpClient).

public class TestClient
{
    private HttpClient Client { get; }
    public TestClient(HttpClient client)
    {
        Client = client;
    }

    public Task<HttpResponseMessage> CallAsync(CancellationToken cancellation = default)
    {
        return client.GetAsync("/", cancellation);
    }
}

Редактировать

(на основе вышеуказанных правок)

Если вы хотите переопределить поведение по умолчанию для метода расширения AddHttpClient, вам следует зарегистрировать свою реализацию напрямую:

var services = new ServiceCollection();
services.AddHttpClient("test", httpClient =>
{
    httpClient.BaseAddress = new Uri("https://localhost");                    
});

services.AddScoped<TestClient>();

var servicesProvider = services.BuildServiceProvider(validateScopes: true);
using (var scope = servicesProvider.CreateScope())
{
    var client = scope.ServiceProvider.GetRequiredService<TestClient>();
}
public class TestClient
{
    private IHttpClientFactory ClientFactory { get; }

    public TestClient(IHttpClientFactory clientFactory)
    {
        ClientFactory = clientFactory;
    }

    public Task<HttpResponseMessage> CallAsync(CancellationToken cancellation = default)
    {
        using (var client = ClientFactory.CreateClient("test"))
        {
            return client.GetAsync("/", cancellation);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...