C#  - Usando Reflection na prática - I

 Neste artigo vou mostrar uma aplicação prática da utilização de Reflection : Gerando um log de auditoria.

Como eu já apresentei o Reflection em outros artigos vou iniciar com um pequeno resumo e depois partir para a prática.

Usando Reflection podemos inspecionar o código em tempo de execução (runtime) e realizar tarefas como :

  • Obter metadados das propriedades e métodos;
  • Instanciar objetos;
  • Chamar métodos e alterar propriedades;
  • Compilar e executar código dinamicamente;

Dessa forma podemos usar Reflection para realizar uma programação genérica onde podemos generalizar o código onde os nomes das propriedades e métodos podem variar.

Então é isso que vou mostrar neste artigo.

Vamos imaginar um cenário onde precisamos logar as informações das nossas classes de domínio em um projeto.

Temos as classes Cliente, Produto e Pedido e precisamos logar as informações.

Vou mostrar como podemos fazer isso sem usar Reflection e depois como o uso de Reflection vai facilitar a nossa vida.

Recursos usados:

Nota: Baixe e use a versão Community 2015 do VS ela é grátis e é equivalente a versão Professional.

Criando a solução no VS 2015 Community

Abra o Visual Studio Community 2015 e clique em New Project;

Selecione Visual C# -> Console Application

Informe o nome UsandoReflection e clique no botão OK.

Criando as classes

Vamos criar as classes Cliente, Produto e Pedido via menu Project Add Class.

A seguir temos o código de cada classe :

1- Cliente

    public class Cliente
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Endereco { get; set; }
    }

2- Produto

    public class Produto
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Descricao { get; set; }
        public Decimal Preco { get; set; }
        public int Estoque { get; set; }
    }

3- Pedido

    public class Pedido
    {
        public int Id { get; set; }
        public int ClienteId { get; set; }
        public DateTime DataPedido { get; set; }
    }

Criando a classe de Log sem usar Reflection

Agora vamos fazer uma implementação bem simples da classe que vai logar as informações que precisamos.

No menu Project clique em Add Class e informe nome LogSemReflection e a seguir inclua o código abaixo nesta classe:

using System;
using System.Text;

namespace UsandoReflection
{
    public class LogSemReflection
    {
        public static void LogProdutos(Produto produto)
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine("Log do produto");
            builder.AppendLine("Data: " + DateTime.Now);
            builder.AppendLine("Id: " + produto.Id);
            builder.AppendLine("Nome: " + produto.Nome);
            builder.AppendLine("Descrição: " + produto.Descricao);
            builder.AppendLine("Estoque: " + produto.Estoque);
            ImprimeLog(builder.ToString());
            //SalvaLog()
        }

        public static void LogPedidos(Pedido pedido)
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine("Log do pedido");
            builder.AppendLine("Data: " + DateTime.Now);
            builder.AppendLine("Id: " + pedido.Id);
            builder.AppendLine("ClienteId: " + pedido.ClienteId);
            builder.AppendLine("DataPedido: " + pedido.DataPedido);
            ImprimeLog(builder.ToString());
        }

        public static void LogClientes(Cliente cliente)
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine("Log do cliente");
            builder.AppendLine("Data: " + DateTime.Now);
            builder.AppendLine("Id: " + cliente.Id);
            builder.AppendLine("Nome: " + cliente.Nome);
            builder.AppendLine("Endereço: " + cliente.Endereco);
            ImprimeLog(builder.ToString());
        }

        public static void ImprimeLog(string texto)
        {
            Console.WriteLine(texto);
        }

        public void SalvaLog(string texto)
        {
            //salva o log
        }
    }
}

Definimos 3 métodos, um para logar as informações de cada classe.  Assim temos os métodos:

  1. LogProdutos
  2. LogClientes
  3. LogPedidos

Essa abordagem é bem ingênua mas é mais comum do que se imagina. Nela para cada classe que desejamos logar vamos ter que criar um novo método na classe LogSemReflection.

Não precisa ser muito esperto para perceber que essa classe fere os princípios das boas práticas da programação e não esta aderente aos princípios SOLID.

A implementação não respeita o princípio da responsabilidade única (SRP)  nem o princípio aberto fechado (Open/Closed). (Sem dizer que estamos repetindo código ferindo o principio DRY.)

Então vamos melhorar o código usando Reflection.

Criando a classe de Log usando Reflection

Agora vamos fazer uma implementação do log usando Reflection e melhorar o nosso código tornando-o mais robusto e aderente às boas práticas.

No menu Project clique em Add Class e informe nome LogComReflection e a seguir inclua o código abaixo nesta classe:

using System;
using System.Text;

namespace UsandoReflection
{
    public class LogComReflection
    {
        //método genérico para criar um log
        //para qualquer classe
        public static void Log(object obj)
        {
            //obtem o tipo do objeto
            //esse tipo não tem relação com a instância de obj

            var tipo = obj.GetType();

            StringBuilder builder = new StringBuilder();
            //obtem o nome do tipo
            builder.AppendLine("Log do " + tipo.Name);
            builder.AppendLine("Data: " + DateTime.Now);

            //Vamos obter agora todas as propriedades do tipo
            //Usamos o método GetProperties para obter
            //o nome das propriedades do tipo
            foreach (var prop in tipo.GetProperties())
            {
                //usa a propriedade Name para obter o nome da propriedade
                //e o método GetValue() para obter o valor da instância desse tipo

                builder.AppendLine(prop.Name + ": " + prop.GetValue(obj));
            }
            ImprimeLog(builder.ToString());
        }

        public static void ImprimeLog(string texto)
        {
            Console.WriteLine(texto);
        }
    }
}

Agora temos um único método genérico que pode ser usado para logar as informações de qualquer classe.

Logando as informações

Apenas para mostrar que o código esta funcional vamos implementar o código que cria instâncias das classes e usa as duas implementações do log.

Abra o arquivo Program e inclua o código a seguir:

using System;
namespace UsandoReflection
{
    class Program
    {
        static void Main(string[] args)
        {
            var cliente = new Cliente()
            {
                Id = 10,
                Nome = "Macoratti",
                Endereco = "Rua Projetada, 100"
            };
            var produto = new Produto()
            {
                Id = 1,
                Nome = "Caderno",
                Descricao = "Caderno Espiral 100 folhas",
                Estoque = 100,
                Preco = 3.99M
            };
            var pedido = new Pedido()
            {
                Id = 1,
                ClienteId = 1,
                DataPedido = DateTime.Now
            };
            Console.WriteLine("***** Logando sem usar Reflection ****");
            LogarSemReflection(cliente, produto, pedido);
            Console.WriteLine(" ---------- Logando usando Reflection ----------");
            LogarUsandoReflection(cliente, produto, pedido);
            Console.ReadKey();
        }		
        public static void LogarSemReflection(Cliente cli, Produto prod, Pedido ped)
        {
            LogSemReflection.LogClientes(cli);
            LogSemReflection.LogProdutos(prod);
            LogSemReflection.LogPedidos(ped);
        }
        public static void LogarUsandoReflection(Cliente cli, Produto prod, Pedido ped)
        {
            LogComReflection.Log(cli);
            LogComReflection.Log(prod);
            LogComReflection.Log(ped);
        }
    }
}
 

 

Executando o projeto teremos o resultado mostrado na figura ao lado.

Na segunda parte do artigo vou mostrar outra aplicação prática de Reflection.

Pegue o projeto completo aqui: UsandoReflection.zip

Aquele que nem mesmo a seu próprio Filho poupou, antes o entregou por todos nós, como nos não dará também com ele todas as coisas?
Romanos 8:32

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

 

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

 

Referências:


José Carlos Macoratti