依赖注入:HttpClient 还是 HttpClientFactory?
Posted
技术标签:
【中文标题】依赖注入:HttpClient 还是 HttpClientFactory?【英文标题】:Dependency injection: HttpClient or HttpClientFactory? 【发布时间】:2019-12-11 06:44:17 【问题描述】:我到处都可以看到在 DI 中创建客户端(基本、命名、键入)的三种主要方法,但我找不到注入 IHttpClientFactory
或 HttpClient
(两者都可能)的方法。
Q1:请问注入IHttpClientFactory
或HttpClient
有什么区别?
Q2:如果IHttpClientFactory
被注入,每次调用我应该使用factory.CreateClient()
吗?
【问题讨论】:
当我在 startup.cs 中设置services.AddHttpClient(c => c.BaseAddress = new Uri("https://api.github.com/"); );
并将 HttpClient
注入我的服务时,它应该使用与注入 IHttpClientFactory.CreateClient()
相同的客户端,对吧?
【参考方案1】:
总结
HttpClient
只能注入到 Typed 客户端
其他用途需要IHttpClientFactory
在这两种情况下,HttpClientMessageHandler
的生命周期都由框架管理,因此您不必担心(错误地)处置 HttpClients
。
示例
为了直接注入HttpClient
,你需要注册一个特定的Typed服务来接收客户端:
services.AddHttpClient<GithubClient>(c => c.BaseAddress = new System.Uri("https://api.github.com"));
现在我们可以将其注入到 typed GithubClient
public class GithubClient
public GithubClient(HttpClient client)
// client.BaseAddress is "https://api.github.com"
您不能在AnotherClient
中注入HttpClient
,因为它没有输入 到AnotherClient
public class AnotherClient
public AnotherClient(HttpClient client)
// InvalidOperationException, can't resolve HttpClient
但是,您可以:
1. 注入IHttpClientFactory
并调用CreateClient()
。此客户端将 BaseAddress
设置为 null
。
2. 或者将AnotherClient
配置为不同类型的客户端,例如使用不同的BaseAdress
。
更新
根据您的评论,您正在注册一个命名客户。它仍然是从 IHttpClientFactory.CreateClient() 方法解决的,但您需要传递客户端的“名称”
注册
services.AddHttpClient("githubClient", c => c.BaseAddress = new System.Uri("https://api.github.com"));
用法
// note that we inject IHttpClientFactory
public HomeController(IHttpClientFactory factory)
this.defaultClient = factory.CreateClient(); // BaseAddress: null
this.namedClient = factory.CreateClient("githubClient"); // BaseAddress: "https://api.github.com"
【讨论】:
是的对不起,我的AddHttpClient的第一个参数是string.Empty
根据您的评论更新了答案并澄清了示例(我希望:D)
如果我在ActionFilterAttribute
中使用HttpClient
怎么办?在这种情况下,您需要使用context.HttpContext.RequestServices.GetService
来获取服务而不是构造函数。【参考方案2】:
遗憾的是,我无法发表评论,只能发布答案。因此,我建议您查看以下链接:
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
关于您的问题,或多或少可以归结为:
Q1 -> IHttpClientFactory 处理 HttpClient 实例的连接池,如果 HttpClient 使用错误,这将帮助您解决链接中描述的加载和处理问题。
Q2 -> 是的,您应该根据微软文档使用 factory.create 客户端
【讨论】:
因此,如果我注入HttpClient
而不是 IHttpClientFactory
(尽管我有相同的 startup.cs 设置),我会失去工厂功能(池等),对吗?我觉得没关系。
一些额外的点作为 HttpClientFactory 内部创建 HttpMessageHandler 对象。因此,每次您在内部创建一个新的 HttpClientFactory 对象时,您都在创建 HttpMessageHandler 对象。并且有一个HttpMessageHandler链。 HttpClientFactory的好处它会重用现有的HttpMessageHandler实例,如果一个可用,如果没有,它会创建一个新的HttpMessageHandler实例以上是关于依赖注入:HttpClient 还是 HttpClientFactory?的主要内容,如果未能解决你的问题,请参考以下文章
当 API 关闭时,Xamarin 表单依赖注入 HttpClient 超时不起作用
如何将 RateLimiter 的 HttpClient DelegatingHandler 与依赖注入一起使用?
如何为构造函数包含 HttpClient 和一些字符串的类设置一些 .NET Core 依赖注入?
当我在 HttpInterceptor 类中注入使用 HttpClient 的服务时,Angular 6 进入循环依赖的无限循环