O NeoMatrix Tech está de casa nova!

Você deverá ser redirecionado em 6 segundos. Se não, visite:
http://www.leonelfraga.com/neomatrixtech
e atualize seus favoritos.

Aviso IMPORTANTÍSSIMO!

Aviso aos navegantes:

O NeoMatrix Tech mudou de casa!!!

A partir de agora, acessem pelo novo endereço:

http://www.leonelfraga.com/neomatrixtech

Ué... mas é só o domínio mudou de lugar?

R: Na verdade, não é bem assim hehe. Este domínio que você acessa agora aponta para um blog hospedado no Blogger, enquanto no novo, aponta para um blog na plataforma Wordpress, hospedagem própria, muito mais rápida e com um layout mais agradável de ler ;)

Não vou fechar este domínio igual ao que eu fiz com o NM Light (que já está 100% na nova plataforma). Talvez beeeeeeem depois eu faça isso.

Todos os posts daqui se encontram lá, e novos posts serão colocados somente no novo endereço.
A única coisa que não consegui importar foram os comentários. Mas em breve vai ter um post contando sobre a epopéia que foi migrar o NeoMatrix Tech!

Somente vou fechar a área de comentários daqui. Caso queiram comentar, favor ver o post correspondente no "Novo NeoMatrix Tech" e comentem por lá. É bem melhor! (pena que os permalinks "amigáveis para SEO" não funcionam lá, dá erro 404 e não consigo fazer a configuração funcionar. E olha que eu já vi vários artigos falando desse assunto :( ).

Quem assina o feed, já está lendo o conteúdo do novo NeoMatrix Tech!

quarta-feira, 6 de maio de 2009

Atribuindo do BD para a classe via Reflection

No primeiro artigo prático da série Reflection na Prática: Uso na Classe de Conexão irei abordar como é construído o método Select() da Classe de Conexão, que além da já tradicional forma de atribuição “manual” faz o uso do Reflection para atribuir os valores de um registro do Banco de Dados para as variáveis privadas (e consequentemente na propriedade que expõe esta variável) da classe que implementa esta tabela.

Antes de entrar no método proprieamente dito, vou lembrar aqui a condição básica para isto funcionar: os campos (variáveis privadas) do objeto DEVEM ser nomeados conforme os campos da tabela do banco de dados precedido de underline. Por exemplo, se tivermos um campo chamado NOME a classe que implementa a tabela deverá ter uma variável privada chamada _NOME.

Com o lembrete, vamos ao método Select:

   1: protected void Select(bool HaveParams)
   2: {
   3:     DataTable dt = this.getTable(this._SelectSQL, HaveParams);
   4:     try
   5:     {
   6:         Type t = this.GetType();
   7:         if (dt.Rows.Count > 0)
   8:         {
   9:             foreach (DataColumn dc in dt.Rows[0].Table.DefaultView.Table.Columns)
  10:             {
  11:                 this.ListaCamposTabela.Add(new TCampoCadastro(dc.ColumnName, dt.Rows[0][dc.ColumnName], dc.Unique));
  12:                 //Bind direto na variável privada, via reflection. Segue convenção: Nome da var. privada = nome do campo da tabela seguido de underline.
  13:                 FieldInfo fi = t.GetField("_" + dc.ColumnName.ToUpper(), BindingFlags.NonPublic | BindingFlags.Instance);
  14:                 if (fi != null)
  15:                 {
  16:                     try
  17:                     {
  18:                         fi.SetValue(this, ConverterDB2Obj(dt.Rows[0][dc.ColumnName], fi.FieldType));
  19:                     }
  20:                     catch
  21:                     {
  22:                         //Não faz nada, esse try..catch é somente para não sair do foreach e manter a compatibilidade com a atribuição manual, dentro da classe derivada.
  23:                     }
  24:                 }
  25:             }
  26:         }
  27:     }
  28:     catch (Exception ex)
  29:     {
  30:         fMsgInfo = ex.Message;
  31:     }
  32:     finally
  33:     {
  34:         dt.Dispose();
  35:     }
  36: }

Para pegar o registro que estamos interessado da base de dados, utilizamos o método GetTable() passando a instrução SQL necessária para fazê-lo e colocamos em um DataTable (sim, ele terá apenas UMA linha, um DataReader poderia ser utilizado para fazer isso também).

Ao verificar se a tabela tem linhas, a brincadeira começa.

Com um laço foreach varro todas as colunas desta tabela, e imediatamente adiciono na coleção ListaCamposTabela uma nova instância da classe TCampoCadastro, que em seu construtor pede o nome da coluna e o valor, e se a coluna pertence à chave.

Para pegar o valor, como no DataTable temos apenas a linha 0, utilizo como índice da coluna o próprio nome da coluna que está na variável “dc”, declarada no foreach.

Este método é o utilizado na versão anterior da Classe de Conexão e foi mantido para manter a compatibilidade com os sistemas em que já está implementado desta forma.

A brincadeira com Reflection começa agora! :-D

A classe FieldInfo contém propriedades para sabermos sobre as propriedades de uma classe, além de fornecer métodos para manipular os valores das propriedades e variáveis privadas (que é o nosso caso) de um objeto.

Antes do foreach, guardo na variável “t”, do tipo Type, as informações sobre os metadados do próprio objeto, que neste caso vai ser do tipo “filho”: lembre-se que a Classe de Conexão é sempre herdada por outro objeto.

Com esta variável, instancio na variável “fi” um objeto do tipo FieldInfo, que para inicializá-lo eu utilizo o método GetField() da classe Type (a nossa variável “t”).

Este método pede como parâmetros o nome da propriedade, que no nosso caso é o nome da coluna do DataTable que está sendo iterada no momento precedido de underline, e os BindingFlags, que são condições que determinam qual será a abrangência dos metadados a serem pesquisados e consequentemente disponíveis no GetField(): BindingFlags.NonPublic indica que queremos que as variáveis privadas estejam na pesquisa, e BindingFlags.Instance indica que queremos que variáveis de instância (não estáticas) estejam incluídas na pesquisa.

Caso o método GetField() retorne alguma coisa, estas informações estarão disponíveis na variável “fi”, e a partir dela poderemos alterar esta propriedade em qualquer objeto da classe que temos na variável “t”.

Para isso, utilizaremos o método SetValue() da classe FieldInfo.

Este método pede como parâmetros o objeto em que a propriedade terá o valor atribuído, no nosso caso, é o próprio objeto, denotado pelo ponteiro this e o valor a ser atribuído, que neste caso é o valor da coluna no registro do DataTable.

A função ConverterDb2Obj faz a conversão do tipo de dado que está no banco de dados para um tipo de dados “destino”, que no nosso caso é o tipo da propriedade que está sendo atribuída. Isto e importante para os casos em que os valores do banco de dados estejam nulos, e vem com o tipo DBNull.Value, que é incompatível com o “null” normal, de objetos.

E esse try…catch com o catch vazio, hein?

Caso dê algum problema na atribuição, ele serve para continuar a iteração nos demais campos da tabela, ou seja, para não haver paradas e para o método “antigo” ainda funcionar.

Com isso, atribuímos diretamente os valores que vem do BD para a classe. Para um exemplo prático, veja os artigos sobre o Simple PIM :-)

Um abraço!

0 comentários:


Postar um comentário

Para tornar este artigo ainda mais interessante, escreva suas críticas (desde que construtivas e sem ofenças), elogios, sugestões, complementos, dúvidas, etc, etc, etc!!!

  © Blogger templates ProBlogger Template by Ourblogtemplates.com 2008 - Editado e configurado por Leonel F.

Voltar ao TOPO