quarta-feira, 2 de novembro de 2011

Serialização e de-serialização genéricas de classes em C#

Olá pessoas!

Depois de alguns meses sem postar nada (envolvido com o Projeto Ingrid), estou de volta com um post bem diferente do habitual: programação em C#.

Nesses últimos meses estive estudando a linguagem e já aprendi (e ainda estou aprendendo) muita coisa interessante. Quis compartilhar um pouco deste aprendizado trazendo um recurso prático para quem desenvolve em .NET e trabalha com serialização de classe.

Para quem já desenvolve em .NET sabe que serialização de classe nada mais é do que salvar uma instância de uma classe em um arquivo físico para que, posteriormente, a classe possa ser recarregada e continuar de onde parou (de-serialização).

O processo de serialização é super tranquilo, pois já trabalha com um código genérico. Veja um método de exemplo:

using System.IO;
using System.Serialization.Formatters.Binary;

public static bool SaveClass(object obj, string fileName)
{
   try
   {
      using (Stream output = File.Create(fileName))
      {
         BinaryFormatter formatter = new BinaryFormatter();
         formatter.Serialize(output, obj);
      }
      return true;
   }
   catch
   {
      return false;
   }
}

No exemplo acima, qualquer classe pode usar este método para a serialização. Basta informar a classe no parâmetro obj. Outro detalhe é que criei o método como estático. Dessa forma, eu posso colocá-lo dentro de uma classe estática de funções e evitar ficar instanciando-a toda vez que precisar serializar.

A sintaxe para utilizá-lo é:

SaveClass(myClassInstance, "c:\myClassInstance.dat");


Já o processo de de-serialização é que a coisa pega.... Veja o exemplo:

using System.IO;
using System.Serialization.Formatters.Binary;

public static myClass LoadClass(string fileName)
{
   try
   {
      using (Stream input = File.OpenRead(fileName))
      {
         myClass obj;
         BinaryFormatter formatter = new BinaryFormatter();
         obj = (myClass)formatter.Deserialize(input);
         return obj;

      }
   }
   catch
   {
      return null;
   }
}

Como podem ver, a de-serialização exige o tipo da classe (myClass) em seu código. Por causa disso, o método de de-serialização precisaria ser criado para cada classe que utilizar este recurso, mudando o tipo da classe na declaração. O código, além de ficar muito repetitivo, seria muito trabalhoso de se manter.

Se houvesse uma forma de passar o tipo da classe como parâmetro, poderíamos utilizar um método mais genérico, assim como na serialização......... Mas calma... Olhem o título do post... Esta forma existe:

using System.IO;
using System.Serialization.Formatters.Binary;

public static T LoadClass< T >(string fileName)
      where T : class
{
   try
   {
      using (Stream input = File.OpenRead(fileName)
      {
         T obj;
         BinaryFormatter formatter = new BinaryFormatter();
         obj = (T)formatter.Deserialize(input);
         return obj;
      }
   }
   catch
   {
      return null;
   }
}

Agora sim, podemos utilizar o método com qualquer classe serializada.

A sintaxe para utilizá-lo é:

myClassInstance = LoadClass< myClass >("c:\myClassInstalce.dat");



Espero que tenham gostado do meu primeiro post de Dev.
Até a próxima!