【问题标题】:Dispose of an XmlWriter without sending outstanding end elements处置 XmlWriter 而不发送未完成的结束元素
【发布时间】:2010-11-17 11:17:33
【问题描述】:

我正在使用XmlWriter 发送 XMPP (Jingle) 流。 XMPP 协议在协商 TLS 时替换了 XML 流,这意味着 XML 最终如下:

<stream>
 <features>
  ...
 </features>

 ...TLS gets negotiated...

<stream>
 ...
</stream>

XML 最终格式不正确,因为有两个流开始标记。

我想要做的是扔掉我在 TLS 协商之前使用的 XmlWriter 并创建一个全新的,它可以让我更好地模块化我的代码。但是,当我调用 myXmlWriter.Close() 以确保它被处理时,它将发送打破 XMPP 协议的关闭流结束元素。

无论如何我可以关闭XmlWriter 而不发送未完成的结束元素吗?

【问题讨论】:

    标签: .net xmpp xmlwriter


    【解决方案1】:

    创建一个中间流,您可以使用它来断开 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; }
        }
    }
    

    此类旨在用作XmlWriterXmlWriter 输出到的流之间的流。这个类只是将所有来自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 方法是否 BaseStreamnull 如果是,则跳过调用。

    【讨论】:

    • 我其实也想过这样做。我过去使用过自定义 Stream 类。我只是希望有一些不那么笨重的东西,哦。
    • 无论您做什么,XmlWriter 都会尽力输出格式良好的 XML。这是解决这个问题的唯一方法。
    猜你喜欢
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    相关资源
    最近更新 更多