Ejemplo básico de serialización de un objeto a formato XML usando la clase XmlSerializer:
using System.IO;
using System.Xml.Serialization;
using System.Text;
// Definición de clases de ejemplo
public class DatosPrincipales
{
public string Identificador { get; set; }
public int Valor { get; set; }
public ElementoSecundario[] Elementos { get; set; }
}
public class ElementoSecundario
{
public double Cantidad { get; set; }
}
// Crear instancia y configurar datos
var instancia = new DatosPrincipales();
instancia.Identificador = "456";
instancia.Valor = 789;
instancia.Elementos = new ElementoSecundario[2];
instancia.Elementos[0] = new ElementoSecundario { Cantidad = 123.45 };
instancia.Elementos[1] = new ElementoSecundario { Cantidad = 678.90 };
// Serializar a flujo de memoria
var serializador = new XmlSerializer(typeof(DatosPrincipales));
using (var flujoMemoria = new MemoryStream())
{
serializador.Serialize(flujoMemoria, instancia);
flujoMemoria.Position = 0;
// Convertir a cadena UTF-8
using (var lector = new StreamReader(flujoMemoria, Encoding.UTF8))
{
string xmlResultado = lector.ReadToEnd();
System.Console.WriteLine(xmlResultado);
}
}
Para deserializar un objeto desde una cadena XML:
string xmlEntrada = xmlResultado; // Cadena XML obtenida previamente
var deserializador = new XmlSerializer(typeof(DatosPrincipales));
using (var lectorCadena = new StringReader(xmlEntrada))
{
var objetoDeserializado = (DatosPrincipales)deserializador.Deserialize(lectorCadena);
// Utilizar objetoDeserializado según necesidad
}
Clase auxiliar para simplificar operaciones de serialización:
using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;
public static class UtilidadesXml
{
// Operaciones con memoria
public static T DeserializarDesdeFlujo<T>(Stream flujo)
{
var serializador = new XmlSerializer(typeof(T));
return (T)serializador.Deserialize(flujo);
}
public static Stream SerializarAFlujo(object objeto)
{
var serializador = new XmlSerializer(objeto.GetType());
var flujo = new MemoryStream();
serializador.Serialize(flujo, objeto);
flujo.Position = 0;
return flujo;
}
// Operaciones con archivos en disco
public static T DeserializarDesdeArchivo<T>(string rutaArchivo)
{
string contenidoXml = File.ReadAllText(rutaArchivo);
return DeserializarDesdeCadena<T>(contenidoXml);
}
public static void SerializarAArchivo(string rutaArchivo, object objeto, Encoding codificacion)
{
string resultadoXml = SerializarACadena(objeto);
if (File.Exists(rutaArchivo)) File.Delete(rutaArchivo);
File.WriteAllText(rutaArchivo, resultadoXml, codificacion);
}
// Operaciones con cadenas
public static T DeserializarDesdeCadena<T>(string xml)
{
var serializador = new XmlSerializer(typeof(T));
using (var lector = new StringReader(xml))
{
return (T)serializador.Deserialize(lector);
}
}
public static string SerializarACadena(object objeto)
{
var serializador = new XmlSerializer(objeto.GetType());
using (var flujo = new MemoryStream())
{
serializador.Serialize(flujo, objeto);
flujo.Position = 0;
using (var lector = new StreamReader(flujo, Encoding.UTF8))
{
return lector.ReadToEnd();
}
}
}
}
Consideraciones importantes para la serialización XML:
- Las clases deben tener un constructor sin parámetros para permitir la deserialización.
- Para tipos complejos no serializables directamente, se requiere aplicar atributos especiales e impleemntar la interfaz
IXmlSerializable. Consultar documentación de Microsoft para detalles. - No se admiten campos de solo lectura en la serialización.
- El soporte para tipos anulables (nullable) en la serialización nativa es limitado; se recomienda evitarlos.
- El atributo
[XmlIgnore]permite excluir miembros específicos del proceso de serialización. - Los tipos Dictionary no son soportados directamente. Se puede usar una implementación personalizada como se muestra a continuación.
- Se soporta la serialización de clases abstractas mediante el uso de atributos de tipo conocido.
- Colecciones como
ArrayListyHashtabletienen soporte deficiente; por ejemplo,ArrayListsolo funciona con tipos de valor. - Para resolver errores de tipo no primitivo, se debe proporcionar un arreglo de tipos adicionales al constructor de
XmlSerializer. - Las propiedades pueden serializarse si disponen de métodos get y set.
Ejemplo de diccionario serializable personalizado:
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
[XmlRoot("diccionario"), Serializable]
public class DiccionarioSerializable<ClaveT, ValorT>
: Dictionary<ClaveT, ValorT>, IXmlSerializable
{
public DiccionarioSerializable() { }
public DiccionarioSerializable(IDictionary<ClaveT, ValorT> diccionario)
: base(diccionario) { }
public DiccionarioSerializable(IEqualityComparer<ClaveT> comparador)
: base(comparador) { }
public DiccionarioSerializable(int capacidad)
: base(capacidad) { }
public DiccionarioSerializable(int capacidad, IEqualityComparer<ClaveT> comparador)
: base(capacidad, comparador) { }
public XmlSchema GetSchema() => null;
public void ReadXml(XmlReader lector)
{
var serializadorClave = new XmlSerializer(typeof(ClaveT));
var serializadorValor = new XmlSerializer(typeof(ValorT));
bool estabaVacio = lector.IsEmptyElement;
lector.Read();
if (estabaVacio) return;
while (lector.NodeType != XmlNodeType.EndElement)
{
lector.ReadStartElement("elemento");
lector.ReadStartElement("clave");
var clave = (ClaveT)serializadorClave.Deserialize(lector);
lector.ReadEndElement();
lector.ReadStartElement("valor");
var valor = (ValorT)serializadorValor.Deserialize(lector);
lector.ReadEndElement();
Add(clave, valor);
lector.ReadEndElement();
lector.MoveToContent();
}
lector.ReadEndElement();
}
public void WriteXml(XmlWriter escritor)
{
var serializadorClave = new XmlSerializer(typeof(ClaveT));
var serializadorValor = new XmlSerializer(typeof(ValorT));
foreach (ClaveT clave in Keys)
{
escritor.WriteStartElement("elemento");
escritor.WriteStartElement("clave");
serializadorClave.Serialize(escritor, clave);
escritor.WriteEndElement();
escritor.WriteStartElement("valor");
ValorT valor = this[clave];
serializadorValor.Serialize(escritor, valor);
escritor.WriteEndElement();
escritor.WriteEndElement();
}
}
}