Domanda

sto usando un XmlWriter per inviare un flusso XMPP (Jingle). Il protocollo XMPP sostituisce l'un flusso XML quando si negozia TLS che significa che il XML finisce come:

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

 ...TLS gets negotiated...

<stream>
 ...
</stream>

La fine XML per non essere ben formati, perché ci sono due tag di inizio flusso.

Quello che voglio fare è buttare via la XmlWriter sto usando, prima di negoziare TLS e creare un nuovo marchio uno, mi permette di modularizzare meglio il mio codice. Tuttavia quando chiamo myXmlWriter.Close() per assicurarsi che venga smaltito invierà l'elemento di chiusura flusso fine, che rompe il protocollo XMPP.

C'è qualche cosa che posso chiudere il XmlWriter senza di essa l'invio del elemento terminale in sospeso?

È stato utile?

Soluzione

Crea un flusso intermedio che è possibile utilizzare per scollegare il XmlWriter dal flusso di base.

Questa non è la soluzione elegante più, e il codice qui sotto lavoro esigenze, in modo da testare prima di mettere questo in produzione, ma è l'idea.

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; }
    }
}

Questa classe è pensato per essere utilizzato come un flusso tra il XmlWriter e il flusso del XmlWriter è l'output a. Questa classe semplicemente inoltra tutte le chiamate dalla XmlWriter al flusso di base, ma una volta che si chiama DisconnectBaseStream, si ferma l'inoltro loro e la XmlWriter non può controllare il flusso di base più.

È possibile utilizzare questa classe in questo modo:

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...
}

Anche in questo caso, il DummyStream è un punto di partenza e avrà bisogno di un certo lavoro. Potrai ad esempio vuole fare in modo che il XmlWriter non sta facendo le chiamate dopo la disconnessione che crash, così si vuole ad alcuni controlli con per esempio il metodo Write se BaseStream è null e se sì, proprio saltare la chiamata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top