martes, 16 de noviembre de 2010

Serialización en .NET

Hoy (y porque me voy a tener que pegar con ello en breve) vamos a hablar sobre la serialización.

Básicamente podríamos decir que la serialización permite:

  • Guardar el estado de un objeto o aplicación.
  • Compartir objetos entre distintas aplicaciones
  • Transmitir objetos entre distintas aplicaciones (por ejemplo Servicios web de ASP.NET, Servicios WCF, etc.)

Un formateador es usado para determinar el formato de la serialización.

NET framework nos suministra distintos formateadores. Los más habituales son:

  • Binario
    • System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
  • SOAP
    • System.Runtime.Serialization.Formatters.Soap.SoapFormatter
  • XML
    • System.Xml.Serialization.XmlSerializer
    • System.Runtime.Serialization.DataContractSerializer
  • JSON
    • System.Web.Script.Serialization.JavascriptSerializer
    • System.Runtime.Serialization.DataContractJsonSerializer

Normalmente el formateador binario se utiliza cuando no se van a pasar datos a través de un firewall (porque un flujo de bytes no suele pasar a través de un firewall, aunque como veremos después cualquier flujo de bytes se puede pasar a texto y vencer esta limitación). Por otro lado, el formateador de SOAP o XML se utiliza para trabajar con texto en vez de bytes y poder así superar la limitación de los cortafuegos. Además, los formateadores SOAP o XML permiten compartir esta información con sistemas externos puesto que su formato es un estándar de facto.

En cualquier proceso de serialización o deserialización interviene los siguientes elementos:

  • El objeto a ser serializado
  • Una stream conteniendo el objeto serializado
  • Un formateador usado para serializar la stream

Tanto con Binario como con SOAP, cualquier clase que quiera ser serializada tiene que incluir el atributo <Serializable()>. Además podemos excluir propiedades de la serialización con el atributo <NonSerialized()>. Fijarse que si trabajamos con propiedades autoimplementadas, tendremos que prescindir de esta característica y hacerlas a la vieja usanza porque el atributo
<NonSerialize()> se aplica a campos de la clase y no a propiedades.

Si una clase tiene propiedades que referencian a objetos de otros tipos, todos esos tipos también tiene que estar marcados como <Serializable()>.

En caso de serializar con XML estos atributos son ignorados y no es necesario adornar la clase ni sus miembros con ningún atributo para que puedan ser serializados. De hecho, el serializador XML puede realizar esta tarea sin ningún atributo extra porque utiliza reflexión para investigar el objeto a serializar.

Tanto en binario como en SOAP, todos los miembros de la clase son serializados incluyendo aquellos con ámbito privado o protegido. Por el contrario con la serialización XML sólo se serializan los miembros públicos.

Si estamos trabajando con XML, si nuestra clase tiene un constructor con parámetros, será necesario crear también de forma explícita un constructor sin parámetros.

La serialización en SOAP y XML no admite la serialización de tipos genéricos (por ejemplo, Dictionary(Of) o List(Of)).

La serialización en XML ya hemos visto que presenta algunas desventajas (necesidad de constructor sin parámetros, sólo serializa los miembros públicos) pero a cambio también ofrece algunas ventajas como que no es necesario marcar la clase como <Serializable()>. En cualquier caso, una de las mayores ventajas de la serialización XML es la capacidad para personalizar la salida de la serialización. De este modo, la serialización XML puede ser personalizada en muchos aspectos a través de atributos. Aquí simplemente se nombran unos pocos:

  • Decidir el nombre del elemento raíz de XML.
  • Decidir si una propiedad se serializa como un elemento XML o como un atributo XML.
  • Ignorar (no serializar) ciertas propiedades.

Para más información visitar “Atributos que controlan la serialización XML” http://msdn.microsoft.com/en-us/library/83y7df3e.aspx

Por último y sin entrar en excesivos detalles, mencionar que cabe la posibilidad de personalizar completamente la serialización (al menos para la serialización binaria y SOAP) a través de la implementación de la interface ISerializable y su método GetObjectData.

Un saludo!

Bibliografía

http://danigarcia.org/?p=350

http://www.codeguru.com/csharp/csharp/cs_syntax/serialization/article.php/c7201

http://www.devjoker.com/contenidos/catss/433/Serializaci%C3%B3n-XmlSerializer-y-BinaryFormater.aspx

http://www.informit.com/articles/article.aspx?p=29457&seqNum=5

http://aaron-powell.spaces.live.com/blog/cns!91A824220E2BF369!150.entry

http://www.west-wind.com/WebLog/posts/218001.aspx

http://www.esasp.net/2010/06/c-serializar-json-datacontract.html

http://www.codeguru.com/columns/dotnet/article.php/c6595

http://msdn.microsoft.com/es-es/library/90c86ass(v=VS.80).aspx

2 comentarios: