2011-07-05 18 views
6

Como resultado de un procedimiento almacenado recibo un objeto SqlXml, desde el que puedo llamar al CreateReader para obtener un estándar XmlReader para poder manejarlo en mi dll.Obtener un flujo de un XmlReader

En la capa de negocio de la aplicación, tengo una XMySerializer que podría leer el xml y una instancia del objeto de negocio.

Sin embargo, la función XMySerializer.Deserialize toma un System.IO.Stream como entrada.

Entonces, la pregunta es ¿cómo podría conseguir un System.IO.Streamde un System.Xml.XmlReader? En sentido contrario sería más fácil ...

Respuesta

3

Creo que no hay forma de obtener la transmisión que usa XmlReader. La Solución alternativa sería usar XmlReader.ReadOuterXml() para obtener todo el XML como una cadena y ponerlo en un MemoryStream.

+0

Tenga en cuenta que esto tiene la sobrecarga de decodificar el XML codificado [generalmente UTF8] (con la mayoría de los bytes individuales por carácter), a una cadena donde cada carácter es de dos bytes (algunos caracteres son más I pensar). Por lo tanto, hay que considerar el costo de decodificación de texto y la huella de memoria de doble tamaño. – redcalx

1

No se puede. XmlReader es una clase abstracta que tiene muchas implementaciones (incluidas algunas que leen de las transmisiones pero otras no tienen nada que ver con las transmisiones). Sin embargo, puede escribir los datos en este lector XML en System.IO.MemoryStream y luego proporcionar esta secuencia a su función XMySerializer.Deserialize.

8

En realidad, puedes.
Solo requiere algunas bibliotecas que no todos usan, porque son parte de BizTalk.
Si tiene acceso al tiempo de ejecución de BizTalk, puede utilizar un XmlTranslatorStream para proporcionar una instancia de una instancia StreamXmlReader:

var xmlStream = new XmlTranslatorStream(xmlReader); 

There are 3 constructors que puede utilizar.

Sí, los requisitos extremadamente importantes para obtener un Stream de un XmlReader, para que pueda ver por qué la mayoría de las respuestas equivale a "no se puede llegar hasta aquí".

Espero que ayude,
Jay

3

El XmlReader puede o no estar respaldado por un Stream. He engañado con algunos métodos usando la reflexión para intentar obtener el Stream o el TextWriter respaldando el XmlReader, pero al final creo que es probablemente más sencillo escribir el objeto en una nueva transmisión; Recomendaría este método sobre la respuesta aceptada porque la respuesta aceptada no funcionará muy bien en documentos grandes, y esta es básicamente una versión simplificada de lo que hará la versión de BizTalk en la respuesta de Jay (BizTalk hace una detección automática de si debe utilizar un FileStream o MemoryStream y tiene alguna otra manejo especial para el XML):

public static class XmlExtensions 
{ 
    public static MemoryStream ToStream(this XmlReader reader) 
    { 
     MemoryStream ms = new MemoryStream(); 
     reader.CopyTo(ms); 
     return ms; 
    } 

    public static FileStream ToStream(this XmlReader reader, string fileName) 
    { 
     FileStream fs = new FileStream(fileName, FileMode.Create); 
     reader.CopyTo(fs); 
     return fs; 
    } 

    public static void CopyTo(this XmlReader reader, Stream s) 
    { 
     XmlWriterSettings settings = new XmlWriterSettings(); 
     settings.CheckCharacters = false; // don't get hung up on technically invalid XML characters 
     settings.CloseOutput = false; // leave the stream open 
     using (XmlWriter writer = XmlWriter.Create(s, settings)) 
     { 
      writer.WriteNode(reader, true); 
     } 
    } 
} 

CopyTo le permitirá configurar su corriente de la manera que quieras; ToStream le ofrece un par de casos comunes útiles en los que simplemente desea obtener rápidamente un MemoryStream regular (para archivos XML más pequeños) o use un FileStream (para los más grandes).

Por supuesto, al final, si es que realmente estás haciendo esto para fines de serialización, que sería bueno añadir sólo una sobrecarga a su clase de serialización como:

XMySerializer.Deserialize(XmlReader reader, object graph) 

Tanto XmlSerializer y en DataContractSerializer el BCL sigue esa idea ...

Cuestiones relacionadas