martes, 21 de julio de 2009

Convertir tus objetos en XML directamente

En algunas ocasiones es necesario guardarse un objeto en su estado actual con todas sus propiedades por ejemplo para guardar en un fichero log, o para transferir por algún protocolo que sólo admite texto, etc. En casos como estos suele ser muy práctico utilizar las clases de serialización que vienen nativas en el Framework.net.

Imaginad que tenemos la típica clase Persona que representa un objeto de negocio de nuestra aplicación:

   1:  Public Class Persona
   2:   
   3:      Private _Nombre As String
   4:      Private _Apellidos As String
   5:   
   6:      Public Property Nombre() As String
   7:          Get
   8:              Return _Nombre
   9:          End Get
  10:          Set(ByVal value As String)
  11:              _Nombre = value
  12:          End Set
  13:      End Property
  14:   
  15:      Public Property Apellidos() As String
  16:          Get
  17:              Return _Apellidos
  18:          End Get
  19:          Set(ByVal value As String)
  20:              _Apellidos = value
  21:          End Set
  22:      End Property
  23:   
  24:      Sub New()
  25:          Me.Nombre = String.Empty
  26:          Me.Apellidos = String.Empty
  27:      End Sub
  28:   
  29:  End Class

Para pasar un objeto de esta clase a String necesitamos utilizar las clases System.Xml.Serialization.XmlSerializer y System.IO.StringWriter de la siguiente forma:

   1:  Dim PersonaSerializada As String
   2:  Dim Yo As New Persona()
   3:  Yo.Nombre = "Yo"
   4:  Yo.Apellidos = "Mismo"
   5:   
   6:  Using sw As New StringWriter()
   7:      Dim serialitzador As New XmlSerializer(GetType(Persona))
   8:      serialitzador.Serialize(sw, Yo)
   9:      PersonaSerializada = sw.ToString()
  10:  End Using

Y el resultado que tendríamos sería:

<?xml version="1.0" encoding="utf-16"?>
<Persona xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Nombre>Yo</Nombre>
<Apellidos>Mismo</Apellidos>
</Persona>

Este es un método práctico y rápido para guardar el estado de un objeto en un momento concreto y puede ser muy útil tanto para poder realizar trazas de un procedimiento concreto o para montar un sistema de gestión de excepciones avanzado .. imaginad que cada vez que se produce una excepción tratando un objeto de negocio nos guardamos la información de la excepción y además el objeto entero.

A tener en cuenta:

  • El objeto System.Xml.Serialization.XmlSerializer también incluye el método Deserialize para cargar el objeto de negocio a partir de un String.
  • Si cambiamos las referencias al objeto System.IO.StringWriter por un System.IO.StreamWriter podemos guardar el objeto serializado en un fichero XML directamente.
  • Los procesos de serialización suelen tener un coste elevado para el sistema así que es conveniente utilizarlo en entornos donde no prime el rendimiento de la aplicación … ¿existe hoy día algún sitio donde no sea imprescindible el rendimiento? .. :-P

lunes, 20 de julio de 2009

Asociar descripción a una Enum

Las Enum nos ofrecen la posibilidad de asociar un nombre descriptivo a un conjunto de valores relacionados entre si, estos valores son numéricos.

Public Enum EstadoCivil 
Soltero
Casado
End Enum

Muchas veces cuando tenemos una Enum tenemos la necesidad de obtener el nombre que le hemos dado a uno de los valores como si fuera un String (pe. “Soltero”) para mostrarlo en un mensaje por pantalla o registrarlo en algún fichero, etc.

Acceso directo al valor

Si queremos acceder directamente al literal que le hemos asociado al valor simplemente debemos utilizar el método ToString() del valor:

EstadoCivil.Soltero.ToString("G")

Esta línea de código nos devolvería el String “Soltero”.

Acceder a la descripción detalla del valor

Si lo que queremos es poder acceder a una información mucho más detallada, deberemos tirar de Reflection. Para empezar deberíamos ampliar la definición de la Enum.

Public Enum EstadoCivil
<Description("Un soltero")> Soltero
<Description("Un casado")> Casado
End Enum

Y la forma de acceder sería la siguiente:

Public Function ObtenerDescripcionEstadoCivil(ByVal estado As EstadoCivil) As String

Dim InformacionEstado As FieldInfo = GetType(EstadoCivil).GetField(estado.ToString("G"))
Dim Descripcion As DescriptionAttribute = InformacionEstado.GetCustomAttributes(GetType(DescriptionAttribute), False)(0)

Return Descripcion.Description

End Function

La llamada a esta función nos daría acceso a la descripción que le hemos asignado.

Etiquetas de Technorati: ,,

sábado, 18 de julio de 2009

Inicialización rápida de objetos

Todos sabemos que las instancias de una clase son iniciadas a través de un constructor y que el constructor es un método de la clase que puede ser sobrecargado. Hasta ahí todo correcto, lo de toda la vida.

Constructores “on fly”

La versión actual de VB.NET nos permite iniciar las propiedades públicas de una clase en el momento de la instanciación, en la misma línea de código. Imaginaros la siguiente clase:



Public Class Persona

Private _Nombre As String
Private _Apellidos As String

Public Property Nombre() As String
Get
Return _Nombre
End Get
Set(ByVal value As String)
_Nombre = value
End Set
End Property

Public Property Apellidos() As String
Get
Return _Apellidos
End Get
Set(ByVal value As String)
_Apellidos = value
End Set
End Property

Sub New()
Me.Nombre = String.Empty
Me.Apellidos = String.Empty
End Sub

End Class

La manera natural de iniciar un objeto de esta clase sería:


Dim NuevaPersona As New Persona()
NuevaPersona.Nombre = "Bill"
NuevaPersona.Apellidos = "Gates


Si quisiéramos poder crear una persona directamente con su Nombre y Apellidos deberíamos sobrecargar el constructor por defecto para que aceptara estos dos nuevos parámetros.


Con la versión actual de VB.NET y sin tener que implementar el nuevo constructor podemos hacer:



Dim BillGates As New Persona() With {.Nombre = "Bill", .Apellidos = "Gates"}


¡Este código es equivalente al del ejemplo de antes pero en una sola línea de código! Y si quisiéramos podríamos ir instanciando diferentes objetos con diferentes propiedades configuradas inicialmente:



Dim Bill As New Persona() With {.Nombre = "Bill"}
Dim BillGates As New Persona() With {.Nombre = "Bill", .Apellidos = "Gates"}



Fácil, ¿no?