注入的 HttpClient 忽略 IHttpClientFactory 配置

Injected HttpClient ignores IHttpClientFactory configuration

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

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

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 容器中获取服务(这是来自测试项目):

var services = new ServiceCollection();

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

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

// Perform test
fooService.DoJob();

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

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

策略处理程序的 absence/existence 在两种情况下都使用调试检查得到确认。

根据我在该主题上找到的所有文档,这两个选项应该是等效的,至少就我最终获得的构造 HttpClient 而言是这样。但这里不是这样。

我找到的文档指定 HttpClient 可以在使用 typed 客户端时注入:

我正在使用类型化客户端,但注入 HttpClient 显然对我不起作用。

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

实际上,您的 FooService class 有以下两个注册:

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

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