我正在使用System.Net.Http.HttpClient
进行一些客户端HTTP通信。我把所有的HTTP放在一个地方,从其余的代码中抽象出来。在一个实例中,我希望将响应内容作为流读取,但是流的使用者与HTTP通信发生的位置和流打开的位置隔离得很好。在负责HTTP通信的现场,我正在处理所有HttpClient
的东西。
此单元测试将在Assert.IsTrue(stream.CanRead)
处失败
[TestMethod]
public async Task DebugStreamedContent()
{
Stream stream = null; // in real life the consumer of the stream is far away
var client = new HttpClient();
client.BaseAddress = new Uri("https://www.google.com/", UriKind.Absolute);
using (var request = new HttpRequestMessage(HttpMethod.Get, "/"))
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
//here I would return the stream to the caller
stream = await response.Content.ReadAsStreamAsync();
}
Assert.IsTrue(stream.CanRead); // FAIL if response is disposed so is the stream
}
我通常尝试尽可能早地处理任何IDisposable
,但在本例中,处理HttpResponseMessage
也会处理从ReadAsStreamAsync
返回的Stream
。
因此,调用代码似乎需要知道响应消息和流,并获得它们的所有权,否则我就不处理响应消息,让终结器处理它。这两种选择都不是正确的。
This answer谈到不处理HttpClient
。HttpRequestMessage
和/或HttpResponseMessage
怎么样?
我是不是遗漏了什么?我希望让使用HTTP的代码对HTTP一无所知,但把这些未处理的对象留在身边有悖于多年的习惯!
发布于 2018-03-02 03:20:28
您还可以将流作为输入参数,这样调用者就可以完全控制流的类型及其处理。现在,您还可以在控件离开该方法之前处理httpResponse。
下面是HttpClient的扩展方法
public static async Task HttpDownloadStreamAsync(this HttpClient httpClient, string url, Stream output)
{
using (var httpResponse = await httpClient.GetAsync(url).ConfigureAwait(false))
{
// Ensures OK status
response.EnsureSuccessStatusCode();
// Get response stream
var result = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
await result.CopyToAsync(output).ConfigureAwait(false);
output.Seek(0L, SeekOrigin.Begin);
}
}
https://stackoverflow.com/questions/27715327
复制相似问题