Pregunta

Al usar .Net, ¿qué limitaciones (si las hay) existen al usar XmlSerializer?Por ejemplo, ¿puedes serializar imágenes a XML?

¿Fue útil?

Solución

XmlSerializer tiene algunos inconvenientes.

  1. Debe conocer todos los tipos que se serializan.No puede pasarle algo por interfaz que represente un tipo que el serializador no conoce.
  2. No puede hacer referencias circulares.
  3. Serializará el mismo objeto varias veces si se hace referencia a él varias veces en el gráfico de objetos.
  4. No se puede manejar la serialización de campos privados.

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

Encontré el NetDataContractSerializador cuando salió WCF.Hace todas las cosas desde arriba que XmlSerializer no hace.Impulsa la serialización de forma 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 altamente.

Otros consejos

En general, considero que XmlSerializer es una mala elección para cualquier POCO que sea más que un simple DTO.Si necesita XML específico, puede seguir la ruta Xml*Attribute y/o IXmlSerializable, pero se quedará con un objeto bastante destrozado.

Para algunos propósitos, sigue siendo una opción obvia, incluso con sus limitaciones.Pero, para simplemente almacenar y recargar datos, he descubierto que BinaryFormatter es una opción mucho más fácil y con menos dificultades.

Aquí hay una lista de algunas molestias con XmlSerializer: la mayoría me han molestado en un momento u otro, otras las encontré en MSDN:

  • Requiere un constructor público, sin argumentos.
  • Solo serializa propiedades y campos públicos de lectura/escritura.
  • Requiere que se conozcan todos los tipos.
  • En realidad llama a get_* y set_*, entonces validación, etc.se ejecutará.Esto puede ser bueno o malo (piense también en el orden de las llamadas)
  • Solo serializará colecciones IEnumerable o ICollection que cumplan con reglas específicas.

XmlSerializer brinda un tratamiento especial a las clases que implementan IEnumerable o ICollection.Una clase que implementa IEnumerable debe implementar un método Add público que toma un único parámetro.El parámetro del método Add debe ser del mismo tipo que el devuelto por la propiedad Current en el valor devuelto por GetEnumerator, o una de las bases de ese tipo.

Una clase que implementa ICollection (como CollectionBase) además de IEnumerable debe tener una propiedad indexada de elemento pública (indexador en C#) que tome un número entero y debe tener una propiedad pública Count de tipo entero.El parámetro del método Add debe ser del mismo tipo que el devuelto por la propiedad Item o una de las bases de ese tipo.Para las clases que implementan ICollection, los valores que se van a serializar se recuperan de la propiedad Item indexada, no llamando a GetEnumerator.

  • No serializa IDictionary
  • Utiliza ensamblados generados dinámicamente, que es posible que no se descarguen del dominio de la aplicación.

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

XmlSerializer.xmlSerializer (tipo) xmlserializer.xmlserializer (tipo, cadena)

Si utiliza cualquiera de los otros constructores, se generan varias versiones del mismo ensamblado y nunca se descargan, lo que provoca una pérdida de memoria y un rendimiento deficiente.

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

No se puede crear una instancia de XmlSerializer para serializar una enumeración si se cumplen las siguientes condiciones:La enumeración es de tipo unsigned long (ulong en C#) y contiene cualquier miembro con un valor mayor que 9,223,372,036,854,775,807.

La clase XmlSerializer ya no serializa objetos marcados como [Obsoletos].

Debe tener permiso para escribir en el directorio temporal (según lo definido por la variable de entorno TEMP) para deserializar un objeto.

  • Requiere leer .InnerException para obtener información útil sobre los errores

Otro problema es que llamar al constructor de XmlSerializer compilará el código en tiempo de ejecución y generará una DLL temporal (en la carpeta %temp%) con el código para realizar la desrialización.

Puede ver el código si agrega las siguientes líneas a app.config:

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

Esto lleva mucho tiempo la primera vez que serializa una clase y necesita código con permisos para compilar y escribir en el disco.

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

Vea aquí para más información.

No estoy seguro si hay alguna limitación.Pero hubo un error de pérdida de memoria en XmlSerialization en .NET 1.1, de alguna manera tuvo que crear un objeto serializador de caché para solucionar este problema...De hecho, no estoy seguro de si este problema se ha solucionado en .net 2.0 o posterior...

En teoría, cualquier clase que escriba puede transmitirse a través de XmlSerializer.Sin embargo, sólo tiene acceso a los campos públicos y las clases deben estar marcadas con los atributos correctos (p. ej.Atributo Xml).Incluso en el marco básico, no todo es compatible con XmlSerializer.System.Collections.Generic.Dictionary<> por ejemplo.

La única limitación que se me ocurre es que XmlSerialization es una opción de exclusión voluntaria;lo que significa que cualquier propiedad de una clase que no desee serializar DEBE estar decorada con [XmlIgnore].En contraste con DataContractSerializer, donde todas las propiedades son voluntarias, debe declarar explícitamente los atributos de inclusión.Aquí hay un buen escribir.

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

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

Para las colecciones, deben tener un método Add que tome un solo argumento.Si solo necesita un formato de texto y no específicamente xml, puede probar JSON.He desarrollado uno para .NET, JsonExSerializador, y hay otros disponibles también en http://www.json.org.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top