Serialización de objetos en XML con C#.NET

De manera análoga a como en Java es posible realizar la serialización de clases a XML, encontré que también es posible hacerlo en C#.NET.  Para esto es necesario que la clase a ser serializada exponga los atributos que desea publicar a través de propiedades.

Para la demostración creé una clase XMLSerializable de la cual heredarán las otras que requieran de este tipo de serialización.  Esta clase abstracta provee los métodos load y save para realizar automáticamente la serialización de sus hijos.

La serialización de los objetos se realiza con el siguiente código.

        public void save(String filename)
        {
            // Creates the writing stream

            StreamWriter w = new StreamWriter(filename);

            // Creates the XML serializer with its type

            XmlSerializer s = new XmlSerializer(this.GetType());

            // Serializes the object (this self -> son)

            s.Serialize(w, this);

            // Closes the output stream

            w.Close();
        }

La carga de objetos serializados requiere de un par de verificiones adicionales.

        public bool load(String filename)
        {
            bool success = false;

            // Checks if the source file exists, otherwise there is nothing to do

            if (File.Exists(filename))
            {
                // Creates the reading stream

                StreamReader sr = new StreamReader(filename);

                // Creates the text reader from the stream

                XmlTextReader xr = new XmlTextReader(sr);

                // Creates the XML (de)serializer with its type

                XmlSerializer xs = new XmlSerializer(this.GetType());

                // Temporary storage object

                object c;

                // Checks if the received data can be deserialized

                if (xs.CanDeserialize(xr))
                {
                    // Deserialize the incoming data

                    c = xs.Deserialize(xr);

                    // Gets the type (definition) of the object

                    Type t = this.GetType();

                    // Retrieve the exposed attributes by properties

                    PropertyInfo[] properties = t.GetProperties();

                    // Walks thru all properties and loads its values on
                    // the local attributes

                    foreach (PropertyInfo p in properties)
                    {
                        p.SetValue(this, p.GetValue(c, null), null);
                    }

                    success = true;
                }

                // Closes the reader and the stream

                xr.Close();
                sr.Close();
            }

            return success;
        }

Con estas facilidades se crea una clase Empleado con atributos básicos.

    public class Empleado : XMLSerializable
    {
        ////////////////////////////////////////////////////////////////

        private int      codigo;
        private String   nombre;
        private float    salario;
        private DateTime fechaNacimiento;

        ////////////////////////////////////////////////////////////////

        // Resto del codigo
    }

Es necesario para la serialización que el objeto tenga propiedades de los atributos a exponer.

        public int Codigo
        {
            get { return codigo; }
            set { codigo = value; }
        }

        public String Nombre
        {
            get { return nombre; }
            set { nombre = value; }
        }

        public float Salario
        {
            get { return salario; }
            set { salario = value; }
        }

        public DateTime FechaNacimiento
        {
            get { return fechaNacimiento; }
            set { fechaNacimiento = value; }
        }

También es necesario que la clase cuente con un constructor sin parámetros además de los que requiera normalmente.

        public Empleado()
        {
            this.codigo          = -1;
            this.nombre          = "Sin nombre";
            this.salario         = -1;
            this.fechaNacimiento = new DateTime(1990, 01, 01);
        }

        ////////////////////////////////////////////////////////////////

        public Empleado(int codigo, String nombre, float salario, DateTime fechaNacimiento)
        {
            this.codigo          = codigo;
            this.nombre          = nombre;
            this.salario         = salario;
            this.fechaNacimiento = fechaNacimiento;
        }

Por facilidad también se sobreescribió el método ToString() para generar su representación en cadena.

        override public String ToString()
        {
            return String.Format("[Empleado: codigo = {0}, nombre = "{1}", salario = ${2}, fechaNacimiento = {3}]",
                                    this.codigo, this.nombre, this.salario, this.fechaNacimiento);
        }

Con todo esto, la aplicación de prueba crea en el primer paso a un objeto Empleado y le da valores iniciales a sus atributos, después de esto solicita su serialización.

            Empleado empleado = new Empleado(123, "Pepito Pimentón", 123456.789f, DateTime.Now);
            empleado.save("empleado.xml");

Posteriormente se crea un segundo Empleado que almacenará la información recuperada de la serialización.  Si la prueba tiene éxito, la información de los dos Empleados deberá coincidir.

            Empleado empleado2 = new Empleado();
            empleado2.load("empleado.xml");

La información presentada a través de salida estándar al ejecutar la aplicación de demostración deberá ser algo similar a lo siguiente.

Writing Object: [Empleado: codigo = 123, nombre = "Pepito Pimentón", salario = $123456,8, fechaNacimiento = 14/09/2008 11:12:10 p.m.]
Read Object:    [Empleado: codigo = 123, nombre = "Pepito Pimentón", salario = $123456,8, fechaNacimiento = 14/09/2008 11:12:10 p.m.]

El documento XML generado es bastante explícito y fácil de realizar su manipulación manual si se llegara a requerir.



  123
  Pepito Pimentón
  123456.789
  2008-09-14T22:39:52.888-05:00

Enlaces:

2 thoughts on “Serialización de objetos en XML con C#.NET”

  1. Excelente ejemplo, como comentario personal los name space utilizados son:

    using System.IO;
    using System.Xml.Serialization;
    using System.Xml;
    using System.Reflection;

    en la clase XMLSerealizable, si es en vb.net reemplazalo por imports el using

Leave a Reply

Your email address will not be published. Required fields are marked *