注入的HttpClient忽略IHttpClientFactory配置 [英] Injected HttpClient ignores IHttpClientFactory configuration
问题描述
我创建了一个自定义库,该库自动为依赖于 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注册了以下两个注册
类:
-
services.AddHttpClient< FooService>()
-
services.AddSingleton< FooService>();
services.AddHttpClient<FooService>()
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屋!