私はSystem.Net.Http.HttpClient
クライアント側の HTTP 通信を行います。HTTP はすべて 1 か所にまとめ、コードの残りの部分から抽象化しています。あるインスタンスでは、応答コンテンツをストリームとして読み取りたいのですが、ストリームのコンシューマーは、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
も処分されます。Stream
ReadAsStreamAsync
したがって、呼び出しコードは、応答メッセージとストリームを認識して所有権を取得する必要があるようです。または、応答メッセージを破棄せずにファイナライザーに処理させる必要があります。どちらのオプションも適切ではないようです。
この答えを処分しないことについて述べていますHttpClient
。HttpRequestMessage
および/または についてはどうでしょうかHttpResponseMessage
?
何か見落としているのでしょうか? 消費コードが HTTP を認識しないようにしたいのですが、これらの未処理のオブジェクトをそのままにしておくのは長年の習慣に反します。
ベストアンサー1
したがって、呼び出しコードは、応答メッセージとストリームを認識して所有権を取得する必要があるようです。または、応答メッセージを破棄せずにファイナライザーに処理させる必要があります。どちらのオプションも適切ではないようです。
この特定のケースでは、ファイナライザーはありませんどちらHttpResponseMessage
もHttpRequestMessage
ファイナライザーを実装しません (これは良いことです)。どちらも破棄しない場合は、GC が開始されるとガベージ コレクションが行われ、その時点で基礎となるストリームへのハンドルが収集されます。
これらのオブジェクトを使用している間は、破棄しないでください。使用後は、処分するステートメントでラップする代わりに、完了したらいつでもusing
明示的に呼び出すことができます。どちらの場合も、使用するコードは、基礎となる HTTP リクエストに関する知識を持つ必要はありません。Dispose