所以,我在Startup.cs中注册了一个带有服务集合的命名客户端:
services.AddHttpClient(someServiceName,
client => client.BaseAddress = baseAddress);
现在可以从我的服务提供商那里注入IHttpClientFactory
。
使用此IHttpClientFactory
,我想出了一个客户端实例:
var client = httpClientFactory.CreateClient(someServiceName)
曾几何时,有必要非常小心处理HttpClient
个实例,因为它是rarely the right thing to do。
但是,现在我们已经HttpClientFactory
,这是否重要了?这个client
应该/可以毫无顾虑地处理吗? e.g。
using (var httpClient = httpClientFactory.CreateClient(someServiceName))
using (var response = await httpClient.PostAsync(somePath, someData))
{
var content = await response.Content.ReadAsAsync<SomeResponse>();
//...
}
答案 0 :(得分:9)
没有。你不应该处置你的客户。更一般地说,你不应该处理通过DI容器检索的任何,在ASP.NET Core中默认是服务集合。生命周期由DI容器管理,因此如果您丢弃客户端,但稍后将其注入某个内容,您将获得ObjectDisposedException
。让容器处理掉。
这实际上是IDisposable
类的常见混淆。如果您的类本身拥有依赖项,您应该亲自实现IDisposable
。如果所有依赖项都是注入,则不应实现IDisposable
,因为它不拥有任何需要处理的东西。同样,你不应该处理注入你班级的任何东西,因为它不拥有这些依赖关系。只处理你特别新的东西。如果您没有看到关键字new
,那么您可能不应该处置。
答案 1 :(得分:3)
不需要调用Dispose
方法,但是由于某些原因,您仍然可以调用它。
证明:HttpClient and lifetime management
不需要处理客户端。 Disposal取消传出的请求,并确保在调用Dispose之后不能使用给定的HttpClient实例。 IHttpClientFactory跟踪并处置HttpClient实例使用的资源。 HttpClient实例通常可以视为不需要处理的.NET对象。
检查source of DefaultHttpClientFactory
:
public HttpClient CreateClient(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var handler = CreateHandler(name);
var client = new HttpClient(handler, disposeHandler: false);
var options = _optionsMonitor.Get(name);
for (var i = 0; i < options.HttpClientActions.Count; i++)
{
options.HttpClientActions[i](client);
}
return client;
}
HttpMessageHandler
的实例存储HttpClient
的非托管资源。在经典方案中,HttpClient
创建HttpMessageHandler
的实例,并在其自身处置时对其进行处置。
您可以在上面的代码中看到HttpClient
的不同实例共享HttpMessageHandler
的单个实例,并且没有对其进行处置(disposeHandler: false
)。
因此,HttpClient.Dispose
的调用没有任何作用。但这并不危险。