優れたエンド・エレメントを送信せずにしたXmlWriterを処分
質問
私はXMPP(ジングル)ストリームを送信するためにXmlWriter
を使用しています。それは次のように終わるXMLを意味TLSを交渉する際にXMPPプロトコルは、XMLストリームを置き換えます:
<stream>
<features>
...
</features>
...TLS gets negotiated...
<stream>
...
</stream>
2ストリームの開始タグがあるので、十分に形成されていないされているアップXML終了。
私は何をしたい、それは私がより良い私のコードをモジュール化することができます、私は前にTLSネゴシエーションに使用していますXmlWriter
を捨てて新しいものを作成することです。しかし、私は確信して、それがXMPPプロトコルを破る終値ストリーム終了要素が送信されます配置されます。
myXmlWriter.Close()
を呼び出すとき
私はそれが優れたエンド要素を送信せずにXmlWriter
を閉じることができとにかくありますか?
解決
を使用すると、基本ストリームからのXmlWriterを切断するために使用できる中間ストリームを作成します。の
あなたは生産にこれを入れる前に、これは、それはそうテスト、最もエレガントなソリューション、およびニーズの作業以下のコードではありませんが、それはアイデアについてです。
public class DummyStream : Stream
{
public DummyStream(Stream baseStream)
{
if (baseStream == null)
throw new ArgumentNullException("baseStream");
BaseStream = baseStream;
}
public Stream BaseStream { get; private set; }
public void DisconnectBaseStream()
{
BaseStream = null;
}
private Stream GetBaseStream()
{
return BaseStream ?? Stream.Null;
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return GetBaseStream().BeginRead(buffer, offset, count, callback, state);
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return GetBaseStream().BeginWrite(buffer, offset, count, callback, state);
}
public override bool CanRead
{
get { return GetBaseStream().CanRead; }
}
public override bool CanSeek
{
get { return GetBaseStream().CanSeek; }
}
public override bool CanTimeout
{
get { return GetBaseStream().CanTimeout; }
}
public override bool CanWrite
{
get { return GetBaseStream().CanWrite; }
}
public override void Close()
{
// We do not close the BaseStream because this stream
// is just a wrapper.
// GetBaseStream().Close();
}
public override ObjRef CreateObjRef(Type requestedType)
{
return GetBaseStream().CreateObjRef(requestedType);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
// We do not dispose the BaseStream because this stream
// is just a wrapper.
}
public override int EndRead(IAsyncResult asyncResult)
{
return GetBaseStream().EndRead(asyncResult);
}
public override void EndWrite(IAsyncResult asyncResult)
{
GetBaseStream().EndWrite(asyncResult);
}
public override bool Equals(object obj)
{
return GetBaseStream().Equals(obj);
}
public override void Flush()
{
GetBaseStream().Flush();
}
public override int GetHashCode()
{
return GetBaseStream().GetHashCode();
}
public override object InitializeLifetimeService()
{
return GetBaseStream().InitializeLifetimeService();
}
public override long Length
{
get { return GetBaseStream().Length; }
}
public override long Position
{
get { return GetBaseStream().Position; }
set { GetBaseStream().Position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return GetBaseStream().Read(buffer, offset, count);
}
public override int ReadByte()
{
return GetBaseStream().ReadByte();
}
public override int ReadTimeout
{
get { return GetBaseStream().ReadTimeout; }
set { GetBaseStream().ReadTimeout = value; }
}
public override long Seek(long offset, SeekOrigin origin)
{
return GetBaseStream().Seek(offset, origin);
}
public override void SetLength(long value)
{
GetBaseStream().SetLength(value);
}
public override string ToString()
{
return GetBaseStream().ToString();
}
public override void Write(byte[] buffer, int offset, int count)
{
GetBaseStream().Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
GetBaseStream().WriteByte(value);
}
public override int WriteTimeout
{
get { return GetBaseStream().WriteTimeout; }
set { GetBaseStream().WriteTimeout = value; }
}
}
このクラスはXmlWriter
とXmlWriter
がに出力されるストリーム間のストリームとして使用されることを意味します。このクラスは、基本ストリームへXmlWriter
から単純に転送したすべてのコールが、あなたはDisconnectBaseStream
を呼び出すと、それはもはやそれとベースストリームを制御することはできませんXmlWriter
の転送を停止します。
あなたはこのように、このクラスを使用することができます:
using (var stream = /* stream used to communicate with */)
{
using (var wrapperStream = new DummyStream(stream))
using (var writer = XmlWriter.Create(wrapperStream))
{
// Do you work here.
// Now, disconnect the dummy stream so that the XML writer
// cannot send more data.
wrapperStream.DisconnectBaseStream();
// End of the using block will close the XmlWriter and it
// cannot send more data to the base stream.
}
// Perform TLS negotiation etc...
}
ここでも、DummyStream
は開始点であり、いくつかの作業が必要になります。あなたは、例えばと、いくつかのチェックをしたいと思うでしょうので、あなたは、たとえば、XmlWriter
がクラッシュします切断後の呼び出しを行っていないことを確認したくなるでしょうWrite
方法がBaseStream
かnull
ありそうならば、単に呼び出しをスキップします。