2008-09-20 12 views

Respuesta

18

El XmlSerializer tiene algunos inconvenientes.

  1. Debe conocer todos los tipos que se serializan. No puede pasarlo por una interfaz que representa un tipo que el serializador no conoce.
  2. No puede hacer referencias circulares.
  3. serializará el mismo objeto varias veces si se hace referencia varias veces en el gráfico del objeto.
  4. No se puede gestionar la serialización de campos privados.

I (estúpidamente) escribí mi propio serializador para solucionar algunos de estos problemas. No hagas eso; es mucho trabajo y encontrarás errores sutiles meses después. Lo único que obtuve al escribir mi propio serializador y formateador fue una mayor apreciación de las minucias involucradas en la serialización de gráficos de objetos.

Encontré el NetDataContractSerializer cuando salió WCF. Hace todas las cosas desde arriba que XmlSerializer no hace. Impulsa la serialización de una manera similar a XmlSerializer. Uno decora varias propiedades o campos con atributos para informar al serializador qué serializar. Reemplacé el serializador personalizado que había escrito con NetDataContractSerializer y quedé muy satisfecho con los resultados. Lo recomendaría muchísimo.

+0

Creo que con 3.5SP1 ya no necesita decorar con DataContract/DataMember. –

+0

+1: NetDataContractSerializer: es uno nuevo para mí. ¡Gracias! – x0n

2

No estoy seguro si hay alguna limitación ... Pero había un error de pérdida de memoria en XmlSerialization en .NET 1.1, tenía que crear un objeto serializador de memoria caché para resolver este problema ... De hecho, no soy seguro si este problema se ha solucionado en .net 2.0 o más reciente ...

+0

¿Por qué alguien menospreció esto? El servicio de Windows que escribí ha estado plagado por esta pérdida de memoria de XMLSerializer, y es bueno difundir la palabra en mi humilde opinión. – Larry

1

La única limitación que se me ocurre es que XmlSerialization es opt-out; es decir, cualquier propiedad de una clase que no desee serializar DEBE estar decorada con [XmlIgnore]. Contraste eso con DataContractSerializer donde todas las propiedades son opt-in, debe declarar explícitamente los atributos de inclusión. Aquí hay un buen write-up.

Las imágenes o sus matrices binarias se serializan como texto codificado en base64 por XmlSerializer.

1

Cualquier clase que escriba se puede alimentar teóricamente a través de XmlSerializer. Howerver, solo tiene acceso a los campos públicos, y las clases deben marcarse con los atributos correctos (por ejemplo, XmlAttribute). Incluso en el marco básico, no todo es compatible con XmlSerializer. System.Collections.Generic.Dictionary <> por ejemplo.

1

Por ejemplo, no puede serializar las clases que implementan la interfaz IDictionary.

0

Para las colecciones necesitan tener un método Agregar tomando un solo argumento. Si solo necesita un formato de texto y no específicamente xml, puede intentar con JSON. He desarrollado uno para .NET, JsonExSerializer, y hay otros disponibles también en http://www.json.org.

22

En general, creo que XmlSerializer es una opción deficiente para cualquier POCO que sea más que una DTO. Si necesita XML específico, puede ir a la ruta Xml * Attribute y/o IXmlSerializable, pero le queda un objeto bastante destrozado.

Para algunos propósitos, sigue siendo una elección obvia, incluso con sus limitaciones.Pero, por el simple hecho de almacenar y volver a cargar datos, he descubierto que BinaryFormatter es una opción mucho más fácil con menos inconvenientes.

Aquí es una lista de algunas molestias con XmlSerializer - más me ha picado en un momento u otro, otros que encontraron encima en MSDN:

  • Requiere un público, sin argumentos constructor Sólo
  • serializa las propiedades y campos públicos de lectura/escritura
  • Requiere que se conozcan todos los tipos
  • Llamadas en realidad a get_ * y set_ *, por lo que se ejecutará la validación, etc. Esto puede ser bueno o malo (pensar en el orden de las llamadas así)
  • única serializará colecciones IEnumerable o ICollection conformes a normas específicas

XmlSerializer da un tratamiento especial a las clases que implementan IEnumerable o ICollection. Una clase que implementa IEnumerable debe implementar un método Public Add que tome un solo parámetro. El parámetro del método Add debe ser del mismo tipo que se devuelve desde la propiedad Current en el valor devuelto por GetEnumerator, o una de las bases de ese tipo.

Una clase que implemente ICollection (como CollectionBase) además de IEnumerable debe tener una propiedad pública indexada de Elemento (indizador en C#) que toma un entero y debe tener una propiedad de Cuenta pública de tipo entero. El parámetro para el método Agregar debe ser del mismo tipo que se devuelve desde la propiedad Artículo o una de las bases de ese tipo. Para las clases que implementan ICollection, los valores que se serializarán se recuperarán de la propiedad del Item indexado, no llamando a GetEnumerator.

  • no serializa IDictionary
  • asambleas Usos generadas dinámicamente, que no pueden quedar descargadas desde el dominio de aplicación.

para aumentar el rendimiento, la infraestructura de serialización XML genera dinámicamente asambleas para serializar y deserializar los tipos especificados. La infraestructura encuentra y reutiliza esos conjuntos. Este comportamiento se produce sólo cuando se utilizan los siguientes constructores:

XmlSerializer.XmlSerializer (Tipo) XmlSerializer.XmlSerializer (Type, String)

Si utiliza cualquiera de los otros constructores, se generan múltiples versiones del mismo conjunto y nunca se descarga, lo que da como resultado una pérdida de memoria y un rendimiento deficiente.

  • No se puede serializar ArrayList [] o Lista <T> []
  • tiene otros casos extremos extraños

XmlSerializer no puede ser instanciada para serializar una enumeración si las siguientes condiciones son true: la enumeración es de tipo unsigned long (ulong en C#) y la enumeración contiene cualquier miembro con un valor mayor a 9,223,372,036,854,775,807.

La clase XmlSerializer ya no serializa los objetos que están marcados como [Obsoleto].

Debe tener permiso para escribir en el directorio temporal (como lo define la variable de entorno TEMP) para deserializar un objeto.

  • Requiere lectura .InnerException para conseguir cualquier información útil sobre errores
+0

¡Por Dios, eso es mucho! de limitaciones! Gracias por los detalles. +1 voto – Phil

3

Otro problema es que una llamada al constructor de XmlSerializer compilará el código en tiempo de ejecución y generará un archivo DLL de temperatura (en el temp% % de carpeta) con el código para hacer la de/serialización.

Usted puede ver el código si se agrega las siguientes líneas a App.config:

<system.diagnostics> 
    <switches> 
     <add name="XmlSerialization.Compilation" value="4"/> 
    </switches> 
    </system.diagnostics> 

Esto toma mucho tiempo la primera vez que serializar una clase y necesita código con permisos para compilar y escribir a disco.

Una forma de evitar esto es precompilar estas DLL utilizando la herramienta sGen.exe que viene con VS 2005+.

Look here for more information.

Cuestiones relacionadas