Capítulo 5 – Serialización

Muchas aplicaciones necesitan almacenar o transferir información almacenada en objetos. .Net tiene varias técnicas de serializacion: Binario, SOAP (Simple Object Access Protocol).

Leccion 1 – Serializando Objetos

Que es serialización?

Se implementa usando el NameSpace System.Runtime.Serialization, es el proceso de serializar y deserializar objetos que son almacenados o transferidos y luego reconstruidos. Se convierte el objeto en una secuencia lineal de bytes y viceversa.

Como Serializar un objeto?
Pasos para serializar objetos:
  • Crear un stream donde se almacenará el objeto serializado.
  • Crear un BinaryFormatter
  • Llamar al método Binaryformatter.Serialize para serializar el objeto y colocar el resultado en el stream.
  • En el método serialize, se le pasa como primer parámetro el Stream y como segundo el objeto a serializar.
Ejemplo:
clip_image001 
  Se crea un archivo y abriéndolo con NotePad se puede ver esto. clip_image003  
 
Como deserializar un objeto
  • Crear un stream para leer el objeto serializado.
  • Crear un BinaryFormatter
  • Crear un nuevo objeto donde almacenar lo deserializado.
  • Llamar al método BinaryFormatter.Deserialize y castearlo al tipo correcto.
clip_image004
Y por pantalla se muestra:
clip_image005   

Como se pueden crear clases que se puedan serializar?
Para que una clase sea serializable, se debe agregar el atributo [Serializable] y esto serializa todo, incluso miembros privados. También es posible controlar la serializacion de manera eficiente dependiendo de los requerimientos. Si se desea que uno de los atributos no sea serializable, se le coloca al costado [NonSerialized] . Ejemplo:
clip_image006
 
 Si un elemento se puede calcular a partir de otros, agregando el atributo [NonSerialized], en 
el proceso de deserializacion, no va a ser inicializado. 
Pero seguramente vamos a necesitar que se calcule antes de que el objeto sea deserializado, 
para eso debemos hacer que nuestra clase implemente la interfaz  IDeserializationCallback, el 
método OnDeserialization(Object sender), el cual se llamará en el momento que el objeto se 
deserialize.
 
clip_image007

Como proveer la compatibilidad de versiones? 
Para superar limitaciones que pueden ser producidas por problemas de compatibilidad, existen 2 opciones. Implementar una serializacion customizada (explicada más adelante – lección 3) Aplicando el atributo para nuevamente agregar los miembros que pueden causar problemas de compatibilidad. El atributo OptionalField que no afectará el proceso de serialización. Pero si es que en el proceso de deserialización el miembro no fue serializado, el valor será dejado en null sin arrojar excepción. Ejemplo

clip_image008   
 
Mejores prácticas para compatibilidad de versiones:
  • Nunca remover un campo serializado.
  • Nunca aplicar NonSerializedAttribute a un atributo que lo era en una versión previa.
  • Nunca cambiar el nombre o tipo de un campo
  • Si se adhiere un nuevo atributo, colocarle OptionalFieldAttribute
  • Si se remueve el atributo NonSerializedAttribute, colocarle OptionalFieldAttribute
  • Para los atributos opcionales, inicializar sus datos en Serialization callback.

  Eligiendo un formato de serializacion 

.Net Framework incluye dos métodos para formatear la información serializada, ambas implementan la interface IRemotingFormatter. BinaryFormatter (en NameSpace System.Runtime.Serialization.Formatters.Binary) es el formato en binario que se le da a nuestros objetos, se debería usar cuando uno conoce que todos los clientes a los que va a transferir el binario, tienen solo aplicaciones en .net framework. SoapFormatter (nameSpace System.Runtime.Serialization.Formatters.Binary.Soap) está basado en el formato en xml, la cual es la forma más confiable de transferir datos a través de la red. Debido a que es un xml, será abierto por cualquier aplicación. Se debe utilizar cuando se requiere portabilidad. Por a su complejidad, es menos eficiente que el BinaryFormatter. 

Como usar SoapFormatter?
  Se debe agregar el namespace System.Runtime.Serialization.Formatters.Binary.Soap y la forma de formatear con SoapFormatter es muy parecido a la de BinaryFormatter, solo se substituye la clase BinaryFormatter por SoapFormatter, aunque el archivo resultante es muy diferente.
clip_image009 
De esta forma se ve el archivo creado: clip_image011 
 
Como controlar la serializacion SOAP? 
Se pueden añadir algunos atributos para controlar el formateo de SOAP:
SoapAttribute para señalar que el atributo va a ser serializado
SoapElement para señalar que la clase va a ser serializada como un elemento XML.
SoapEnum para enumeradores
SoapIgnore para no considerar este campo al momento de la serialización
SoapInclude cuando este tipo debe ser incluido cuando se generan esquemas.

Recomendaciones sobre la serializacion 
Ante la duda, se debe colocar como serializable a clases que incluso no se serializarán en ese momento, porque en el futuro se pueden llegar a necesitar. Se debería deshabilitar la serialización para elementos que son calculados o temporales.  
 
Lección 2 – Serializacion XML 
XML es un estándar, un formato de documento basado en texto que puede ser leído por las computadoras. Al igual que HTML posee un formato que puede ser leido y entendido fácilmente por nosotros. Se pueden almacenar imágenes, música, archivos binarios, e incluso información de base de datos.

   Porque usa la serializacion XML? 
Serializacion en XML es usada cuando se necesita intercambiar un objeto con una aplicación que no esté basada en el framework .Net. Provee los siguientes beneficios:
  • Gran interoperabilidad: XML está basado en archivos estándares, y existen muchas librerías para que cualquier aplicación de diferentes sistemas operativos lo pueda usar.
  • Una administración más amigable: puede ser editado desde cualquier editor de texto.
  • Provee archivos más fáciles de leer: se describe por sí solo. Solo puede serializar datos públicos, no privados, No se pueden serializar grafos.
  Como usar XML para serializar/deserializar un objeto? 
Crear un stream, textwriter o un xmlWriter para almacenar los datos. Crear un XmlSerializer pasando el objeto que queremos serializar. Llamar al metodo XmlSerializer.Serialize (si queremos serializar) o XmlSerializer.Deserialize (para deserializar) El código es similar al estándar de serialización, por eso solo voy a colocar el código para serializar Xml. Ejemplo:

clip_image012  

  Como crear una clase que pueda ser serializada usando la serialización xml?
  • · Se debe especificar la clase como pública.
  • · Definir todos los miembros que se desean deserializar como públicos.
  • · Crear un constructor sin parámetros
A diferencia de los otros tipos de serialización, la clase no necesita tener el atributo “Serializable” para poder ser serializado como XML.

  Como controlar la serialización XML? 
Una clase que no tiene ningún atributo para la serialización en XML, se serializaría a XML donde cada uno de sus miembros es un elemento XML, por ejemplo: 
<?xml version="1.0" ?>
   <Clase>
      <att1>valor</att1> 
      <att2>otrovalor</att2> 
</Clase>
Si estamos definiendo un esquema XML, es suficiente, pero si queremos realizar un documento XML, con estándares específicos, necesitamos agregar algunos atributos para controlarlo. Por ej. (los más usados):
XmlAttribute: permite que el campo, se vuelva un atributo en el momento de la serializacion, es decir estará de la siguiente forma
<Clase att1 = "valor">
    ...
</Clase>
XmlIgnore: permite ignorar un atributo para que no sea serializado (como [NonSerialized]).
XmlRoot: ("nombre"), sirve para especificar con otro nombre serializado a la clase que se piensa serializar.
clip_image013 
  
Podemos tomar control sobre la serialización en XML, si implementamos la interfaz IXmlSerializable con sus métodos ReadXml y WriteXml para controlar el XmlReader y XmlWriter.

 Como generar un esquema XML? 
Un esquema Xml define la estructura de un documento Xml. Se puede utilizar la herramienta (xsd.exe) que permite generar un esquema personalizado o estándar(como clase) para las clases que se piensan serializar.  
 
Como serializar un Dataset? 
Las instancias de DataSet pueden ser serializadas a XML. Se serializa de la misma forma que los otros objeto, pero no provee un control de lectura que debería de tener. De forma alterna, se puede utilizar DataSet.WriteXml, DataSet.ReadXML y DataSet.GetXml. Ejemplo:
clip_image014


Lección 3 – Serialización personalizada
Controlando la serialización es posible asegurarnos la compatibilidad entre distintas versiones.

Como implementar la serialización personalizada?
Cuando se desea hacer una serialización customizada, se debe de implementar la interfaz ISerializable, el método GetObjectData, además un constructor para el proceso de serialización con los parámetros: SerializationInfo info, StreamingContext context. Del SerializationInfo (es de donde se obtienen los datos de la forma info.GetInt32("numero"))
clip_image001[1]
 
Respondiendo a los eventos de serialización
.Net Framework soporta eventos de serialización binaria cuando usamos la clase BinaryFormatter. Hay cuatro eventos:
  • OnSerializing: antes de que se serialize
  • OnSerialized: después de la serialización
  • OnDeserializing: antes de que se dé la deserialización
  • OnDeserialized: después de la deserialización y de OnDeserializing
(Estos 4 eventos solo se realizan en la serialización binaria, no en SOAP ni en la customizada.)
Usando eventos es la forma más fácil de controlar el proceso de serialización.
Los métodos permite modificar los objetos antes y después de la serialización/ deserialización.
Para que un método responda a los eventos, debe cumplir con estos requerimientos:
  • aceptar como parámetro un StreamingContext.
  • Retornar void
  • Tener un atributo que concuerde con la definición del evento que se quiere interceptar.
Ejemplo:
clip_image002
 
Como cambiar la serialización basada en el contexto?
Generalmente cuando se serializa, el destino no interesa, pero a veces la serialización y deserialización depende del destino.
La estructura StreamingContext provee información acerca del destino de un objeto serializado para una clase que implementa la interface ISerializable.
StreamingContext tiene 2 propiedades importantes:
  • context.- Es una referencia a un objeto que posee la información deseada por el usuario.
  • State.- Es una serie de bits que funcionan como flags, pueden indicar:
    • CrossProcess.- La fuente o destino es un diferente proceso en la misma máquina.
    • CrossMachine.- La fuente o destino está en una diferente máquina
    • File.- La fuente o destino es un archivo
    • Persistence.- La fuente o destino es una base de datos, un archivo u otro.
    • Remoting.- La fuente o destino es remota a un sitio desconocido.
    • Other.- La fuente o destino es desconocida.
    • Close.- El objeto grafo está siendo clonado.
    • CrossAppDomain.- La fuente o destino es un diferente AppDomain.
    • All.- Es un contexto por default
Cuando uno construye su formateador, éste automáticamente setea su Context a null y su State a All.

Como crear un Custom Formatter?
Para crear un Custom Formatter, se debe implementar la interfaz IFormatter o IGenericFormatter.Tanto BinaryFormatter como SoapFormatter implementan solo la interfaz IFormatter. La clase FormatterServices provee métodos estáticos para ayudar con la implementación del Formatter.



....................................................................................................................................................
Bajar esta capítulo en formato PDF                                                           Codigo Ejemplo
.................................................................................................................................................... 

1 comentario: