segunda-feira, 27 de abril de 2009

Reflection

Apesar de o C# se destacar por ser uma linguagem estática, de código gerenciado e fortemente tipada, volta e meia nos deparamos com a necessidade de acessar recursos que estão fora deste ambiente gerenciado, de uma forma um pouco mais dinâmica.

Essa não é uma necessidade nova, porém recentemente muito tem se falado de linguagens dinâmicas na plataforma .NET, como os IronPhyton e IronRuby, e até um Dynamic C#, que parece que vai estar aí na versão 4 da linguagem.Enquanto essas novidades não chegam e mostram serviço, a solução mais comum que temos para esse tipo de necessidade é o famoso Reflection do .NET.

O Reflection nos oferece uma forma de encapsularmos assemblies. Ou seja, você pode utilizar o Reflection para acessar um assembly que não esteja diretamente referenciado em seu projeto, e obviamente, utilizar as classes e métodos do mesmo, fazendo um acesso dinâmico a estes recursos.

Veja na listagem abaixo um exemplo clássico de como acessar um assembly através de Reflection. O resultado você confere na figura logo a seguir

System.Reflection.Assembly o = 
System.Reflection.Assembly.Load(
"mscorlib.dll");
MessageBox.Show(o.GetName().ToString());




Mas qual a vantagem de utilizarmos o Reflection? O exemplo mais prático e útil que eu conheço do uso do Reflection, é a chamada dinâmica de métodos, seja de um assembly externo ou não.

Imagine que durante a execução da sua aplicação você tenha que calcular os Impostos de uma Nota Fiscal. Porém, o calculo do Imposto depende diretamente do Estado de Destino desta Nota. Sendo assim temos uma rotina ou método para cada Estado.

Que tal colocar essas informações na tabela de Estado, e fazer uma chamada dinâmica à estes métodos. Veja na próxima figura como ficaria a nossa tabela de Estados.



Note que a coluna Metodo armazena apenas uma string que irá representar o nome do método a ser chamado. Sendo assim, podemos ter estes métodos onde desejarmos, veja o exemplo da próxima listagem:



private void button1_Click(object sender, EventArgs e)
{
// Essa informacao pose ser pesquisada no
// database
string NomeMetodo = "Imposto_MG";

// Você pode enviar quantos parametros quiser
object[] Parametros = new object[1];
Parametros[0] = 100.00;

double Vr_Imposto = 0;

// Procurando metodo pelo Nome, no assembly
// atual
System.Reflection.MethodInfo metodo =
this.GetType().GetMethod(NomeMetodo);
if (metodo != null)
Vr_Imposto =
(double)metodo.Invoke(this, Parametros);

MessageBox.Show(Vr_Imposto.ToString());
}

/// Rotina para calculo do Imposto para SP
public double Imposto_SP(double Vr_Nota)
{
return Vr_Nota * 0.12;
}

/// Rotina para calculo do Imposto para RJ
public double Imposto_RJ(double Vr_Nota)
{
return Vr_Nota * 0.07;
}

/// Rotina para calculo do Imposto para MG
public double Imposto_MG(double Vr_Nota)
{
return Vr_Nota * 0.18;
}

Veja que temos três métodos para o calculo do Imposto, um para cada Estado cadastrado na tabela. Em todos os métodos recebemos como parâmetro o valor da Nota Fiscal, e retornarmos o imposto calculado.

Neste exemplo estamos fazendo a chamada no evento click de um botão qualquer. Veja que o nome do método foi colocado como Imposto_MG, mas esta informação obviamente deve ser recuperada do database, ou da onde você desejar.

Note que estamos criando um objeto para encapsular os parâmetros, e em seguida através do método GetMethod, criamos uma referencia ao método com o nome que está na variável NomeMetodo. Em seguida estamos fazendo a chamada deste método através do método Invoke.

Faça alguns testes e veja que o método chamado será sempre o indicado na string NomeMetodo.

É claro que o Reflection não se resume a isso, temos um namespace inteiro dedicado a ele (System.Reflection). Mas essa é sem dúvida uma ótima forma de fazer chamadas dinâmicas, tornando a lógica da sua aplicação bem mais flexível.

Nenhum comentário:

Postar um comentário