Streamオブジェクトを消費せずに読み込む

私はXML-RPC.NETを使用しています( http://www.xml-rpc.net/)と特定のネットワークポート上のXML-RPC通信をリッスンし、それに応答するHttpListenerメソッド。

入力されるリクエストの本体は、 HttpListenerContextInstance.Request.InputStream Streamオブジェクトを介してアクセスできます。

HttpListener hlListener = new HttpListener();
HttpListenerContext hlcContext = hlListener.GetContext();
// hlcContext.Request.InputStream contains what I want

ストリームは hlcContext.Request.InputStream からアクセスできますが、このストリームはシーク可能ではありませんので、読み込み/表示できず、XML-RPCの先頭に戻ります。 NETライブラリは、必要に応じてそれを使用することができます。一度読んだら、それは消費され、再読めません。

私はこの状況を処理する一つの方法はストリームをMemoryStreamに変換してシークをサポートすることだと理解していますが、XML-RPC.NETがMemoryStreamを使用し続けるようにこれを行う方法はわかりませんストリームの代わりにStreamをMemoryStreamにコピーするだけでStreamが消えてしまい、その時点で使用できなくなってしまったようです。

// hlcContext.Request.InputStream is currently filled
MemoryStream msInput = new MemoryStream();
hlcContext.Request.InputStream.CopyTo(msInput);
byte[] byteInput = msInput.ToArray();
// hlcContext.Request.InputStream is now empty and XML-RPC.NET can no longer use it :(

Streamから読み込み、それをStringに格納し、その時点からStreamがXML-RPC.NETで引き続き使用できるようにするにはどうすればよいですか?

0
どのようにストリームをXML-RPC.NETに提供していますか?私はあなたのサンプルコードではそれを見ません。
追加された 著者 Roger Lipscombe,
私はコードを調べる時間がありませんでしたが、 HttpListener がXML RPCタイプであると仮定すると、それをサブクラス化して GetContext()必要な動作を注入するように実装されています。
追加された 著者 Andras Zoltan,
IHttpRequest.InputStreamを変更し、セッターを追加します。すべての実装を修正してください。
追加された 著者 Hans Passant,
Streamは、ウェブサイトにアクセスするたびに( localhost/DoSomething )いつでも/どこかでXML-RPC.NETライブラリによって作成されます。
追加された 著者 Coder6841,
ありがとうHans、これは良いと思うが、私は初心者のプログラマーであり、これを行う構文については不明である。それは次のようなものでしょうか? public class EditableHttpRequest:IHttpRequest {System.IO.Stream InputStream; public System.IO.Stream InputStream {get;セット; } //ここでInputStreamで何かするか?
追加された 著者 Coder6841,

2 答え

正当な方法が見つからない場合、ここではストリームを Request.InputStream に設定するためのハックがあります(最後の手段として)

MemoryStream msInput = new MemoryStream();
hlcContext.Request.InputStream.CopyTo(msInput);
byte[] byteInput = msInput.ToArray();
msInput.Seek(0, SeekOrigin.Begin);

request.GetType().InvokeMember("m_RequestStream", BindingFlags.SetField | BindingFlags.Instance | BindingFlags.NonPublic, null, request, new object[] { msInput });

Now you can freely use byteInput

1
追加された
@ Coder6841、私は不安定になるとは思わない。このコードを使用すると、 request オブジェクトのプライベート変数( m_RequestStream )にアクセスできます。もしMSがあなたにそれをしたければ、それはそれを公開としてマークします。これは、.NET Frameworkの次期リリースで変更される可能性があることを意味します(これまでのバージョンでは何の変更も見られませんでしたが)
追加された 著者 L.B,
それをハック/最後の手段にするこのコードについてはどうですか?それは不安定性をもたらしますか?アプリケーションが重要なビジネスアプリケーションであるため、予期しない問題が発生する可能性がある場合は、使用しないことをお勧めします。
追加された 著者 Coder6841,
これは完璧に動作します、ありがとう!
追加された 著者 Coder6841,

これは、シークをサポートするストリーム( CanSeek == true)。

MemoryStream msInput = new MemoryStream();
var preCopyPosition = hlcContext.Request.InputStream.Position;

hlcContext.Request.InputStream.CopyTo(msInput);
byte[] byteInput = msInput.ToArray();

// Go back to pre-copy state
hlcContext.Request.InputStream.Position = preCopyPosition;
0
追加された
OK。コピーを防ぐためにこれを残しておきます。
追加された 著者 Austin Salonen,
残念ながら、ストリームはシークをサポートしていません。 "hlcContext.Request.InputStream.Position = preCopyPosition;"サポートされていない例外が発生します。
追加された 著者 Coder6841,