注入的HttpClient忽略IHttpClientFactory配置 [英] Injected HttpClient ignores IHttpClientFactory configuration

查看:206
本文介绍了注入的HttpClient忽略IHttpClientFactory配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个自定义库,该库自动为依赖于 HttpClient 的特定服务设置Polly策略。

I've created a custom library which automatically sets up Polly policies for specific services which depend on HttpClient.

这是使用 IServiceCollection 扩展方法和类型化的客户端方法来完成。简化示例:

This is done using the IServiceCollection extension methods and the typed client approach. A simplified example:

public static IHttpClientBuilder SetUpFooServiceHttpClient(this IServiceCollection services)
{
    return services
            .AddHttpClient<FooService>()
            .AddPolicyHandler(GetRetryPolicy());
} 

示例服务:

public class FooService
{
    private readonly HttpClient _client;

    // OPTION 1
    public FooService(HttpClient httpClient)
    {
        _client = httpClient;
    }

    // OPTION 2
    public FooService(IHttpClientFactory httpClientFactory)
    {
        _client = httpClientFactory.CreateClient(GetType().Name);
    }

    public void DoJob()
    {
         var test = _client.GetAsync("http://example.com");
    }
}

从DI容器中获取服务(来自测试项目) :

Fetching the service from the DI container (this is from a test project):

var services = new ServiceCollection();

services.SetUpFooServiceHttpClient();
        
services.AddSingleton<FooService>();

var fooService = services
                   .BuildServiceProvider()
                   .GetRequiredService<FooService>();

// Perform test
fooService.DoJob();

注意:在此测试项目中,我还添加了一个额外的模拟处理程序,因为我试图模拟http状态响应,但是否存在模拟的处理程序与是否存在Polly策略相同,因此我从示例代码中省略了模拟的处理程序。

注意 FooService 中的两个不同的构造函数。根据我注释掉的哪一个以及我留下的哪一个,我得到不同的结果。其他所有代码保持不变。

Notice the two different constructors in FooService. Depending on which one I comment out and which one I leave in, I get different outcomes. All other code remains untouched.


  • 选项1直接注入 HttpClient ,将忽略我的所有配置。我得到一个没有Polly策略处理程序的标准http客户端。

  • 选项2,注入 IHttpClientFactory 并使用当前类型请求客户端名称(即 FooService )尊重我的配置。我得到一个自定义的http客户端,其中包含Polly策略处理程序(以及我可能已配置的任何其他处理程序,例如测试套件中的模拟处理程序)

  • Option 1, injecting the HttpClient directly, ignores all my configuration. I get a standard http client with no Polly policy handler.
  • Options 2, injecting the IHttpClientFactory and requesting the client using the current type name (i.e. FooService) respect my configuration. I get a custom http client which contains the Polly policy handler (and any other handlers I may have configured, e.g. mocked handlers in my test suite)

在两种情况下都使用调试检查来确认策略处理程序的不存在/存在。

The absence/existence of the policy handler is confirmed in both cases using debug inspection.

根据我在该主题上找到的所有文档,至少在以下方面,这两个选项应等效最后获得的构造后的 HttpClient

According to all documentation I've found on the subject, both options should be equivalent, at least in regards to the constructed HttpClient that I obtain in the end. But that is not the case here.

我发现的文档指定使用 typed 时可以注入 HttpClient 。 strong>客户:

The documentation I find specifies that HttpClient can be injected when using typed clients:

  • The MSDN documentation, specifically the "typed clients" section example.
  • This SO answer
  • This blog post

我正在使用类型化的客户端,但是注入 HttpClient 显然并没有

I'm using a typed client but injecting a HttpClient clearly doesn't work for me.

为什么注入 HttpClient 与注入 IHttpClientFactory 在我的情况下工作是否不同?

Why does injecting a HttpClient vs injecting IHttpClientFactory work differently in my case?

推荐答案

实际上,您为 FooService注册了以下两个注册类:


  1. services.AddHttpClient< FooService>()

  2. services.AddSingleton< FooService>();

  1. services.AddHttpClient<FooService>()
  2. services.AddSingleton<FooService>();

由于DI容器在幕后的工作方式,因此第二个注册将覆盖第一个。如果删除第二个注册,则将使用第一个注册,因此将调用带有 HttpClient 参数的构造函数。

Because of how the DI container works behind-the-scenes, the second registration overwrites the first. If you remove the second registration, the first will be used, and so your constructor with the HttpClient parameter will be invoked.

这篇关于注入的HttpClient忽略IHttpClientFactory配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆