Código Sobre Código Sobre Código...
Olá pessoal! Andei um pouco (muito) sumido, mas não esqueci do blog não!
Desde o último post decidi que escreveria o próximo sobre algo mais técnico. Só não conseguia escolher dentre as infinitas possibilidades! Mas afinal pensei: “Esquece o perfeccionismo e escreve logo!”. Então lá vai!
Contextualizando
Recentemente, precisei desenvolver uma funcionalidade para corrigir um problema tenso de integração entre 2 sistemas. O processo anterior acontecia por meio de tabelas intermediárias e jobs no banco de dados que as populavam, para que o sistema destino pudesse (por meio de outro job) gravar as informações nas tabelas finais! Era um processo que apesar de muito sujeito a erros, até que funcionava bem, já estava há um certo tempo em produção.
Porém, ao começar a existir alguns códigos internos divergentes entre os dois, muitos erros passaram a acontecer, inclusive no processo de vendas, que geralmente sempre geram um grande impacto, afinal “Time is Money”!
Solução e Novo Desafio
Para resolver o problema, após diversas análises e sugestões, chegamos à única solução possível: alterar toda a lógica da integração e todos os processos relacionados, substituir as tabelas temporárias e jobs por chamadas ao WebService do sistema destino, utilizando também o código deste como “chave-primária” (que antes era gerada na origem).
Não posso descrever os detalhes do processo em si, mas em resumo, para esta solução funcionar, eu teria que montar um XML com todos os dados que seriam gravados, pois era o único parâmetro recebido pelo WebService. Em parte, o trabalho de criação do objeto que seria enviado e suas muuuitas propriedades (inclusive sendo algumas delas outros objetos) já estava codificado. Porém, surgiu um novo probleminha: no parâmetro a ser enviado, os campos que não estivessem preenchidos (por exemplo, o campo Complemento em um endereço) não poderiam nem fazer parte do XML.
Depois de um tempo montando diversos if‘s para verificar se cada uma das propriedades tinha valor e, caso tivesse, montando o elemento XML “na mão” e com strings hard-coded, parei e refleti um pouco mais… “Vou usar Reflection!”.
Refletindo Sobre o Código
A meta-programação sempre me chamou muito a atenção. Já havia usado um pouco em outros projetos, mas quando encarei este problema de montar um XML dinâmico, vi uma oportunidade de usar ainda mais.
Então comecei a desenvolver, desde o mais genérico e prático, até alguns detalhes que foram surgindo para lidar com casos específicos ou mesmo opções para tornar a geração ainda mais flexível. O esqueleto da classe e método foi esse:
Portanto, ao receber qualquer objeto, que no caso seriam minhas classes já existentes, eu iria retornar uma string, que seria o XML dinâmico. Basicamente, teria que obter os nomes das propriedades, escrevendo aquelas que tivesse algum valor no formato de um elemento XML, ou seja, Valor da propriedade. Então, como percorrer as propriedades?
Assim:
Agora sim as coisas estão ficando mais interessantes! :)
Toda a “mágica” começa na linha 5, onde obtemos qual é o tipo do objeto recebido, e com isso todas as informações daquela classe e suas propriedades! Mas para isso precisamos complementar nosso código inserindo o using do namespace System.Reflection, que nos permitirá percorrer estas propriedades e usar outros métodos (linha 7 e seguintes).
Os detalhes de cada propriedade ficam contidas na classe PropertyInfo, que usamos dentro do foreach, e que nos permitirão obter seu nome e valor.
Na linha 9, verificamos se a propriedade pode ser lida (ou seja, se possui um método get acessível). Caso tenha, obtemos seu nome na linha 9, pela propriedade Name. Também já criamos a variável tagValue do tipo dynamic, que armazenará o valor da propriedade atual, independente de seu tipo.
Bem, a solução final tem mais alguns detalhes bem interessantes, que compartilharei no próximo(s) post(s)! Estou também preparando os arquivos com a solução completa para compartilhar no GitHub, vamos ver quando sai do forno!
Enquanto isso, comente o que achou até aqui! Você já usou Reflection? Como? Faria algo diferente do que eu fiz?
Compartilha aí! ;)