Mostrando postagens com marcador tipagem dinâmica. Mostrar todas as postagens
Mostrando postagens com marcador tipagem dinâmica. Mostrar todas as postagens

domingo, 28 de abril de 2013

Dynamic Method Binding

Já não é novidade que a partir da versão 4 do .NET Framework e da linguagem C# é possível declarar objetos com tipagem dinâmica. Veja este link para mais detalhes.

Em C#, quando um objeto é declarado como dynamic, o compilador nos permite invocar qualquer método a partir desse objeto, sem checar em tempo de compilação se este método existe ou não. Esse recurso é conhecido como Dynamic Method Binding e apenas em tempo de execução o Framework irá informar, através de uma exceção, que o método invocado não existe.

Exemplo: 
dynamic objetoDesconhecido = ObtemObjetoDesconhecidoDeAlgumLugar();
objetoDesconhecido.MetodoQueNaoExiste(); // Compila mas não executa
Não quero discutir aqui o propósito dessa inclusão à linguagem, quero apenas apresentar uma construção bastante interessante permitida com o uso desse recurso.

Imagine escrever um conjunto de métodos privados sobrecarregados, cada um tratando um tipo específico de entrada e delegar a um único método público a função de decidir qual dos métodos privados deve ser executado.

O exemplo abaixo faz isso:
public class Taxonomy
{
    public string GenusFor(IAnimal animal) {
        if (animal is Lion)
            return GenusFor((Lion)animal);
        if (animal is Zebra)
            return GenusFor((Zebra)animal);
        if (animal is Elephant)
            return GenusFor((Elephant)animal);
        return null;
    }
    private string GenusFor(Lion lion) {
        return "Lion";
    }
    private string GenusFor(Zebra zebra) {
        return "Zebra";
    }
    private string GenusFor(Elephant elephant) {
        return "Elephant";
    }
}
O código acima pode parecer desnecessário se considerarmos que o genero do animal poderia ser uma simples propriedade da interface IAnimal, no entanto serve bem para ilustrar a ideia.

Veja como esse mesmo código ficaria se utilizássemos tipagem dinâmica para deixar que o .NET Framework decida em tempo de execução qual a versão do método GenusFor deve ser executada:
public class Taxonomy
{
    public string GenusFor(IAnimal animal) {
        return ((dynamic)this).GenusFor((dynamic)animal);
    }
    private string GenusFor(Lion lion) {
        return "Lion";
    }
    private string GenusFor(Zebra zebra) {
        return "Zebra";
    }
    private string GenusFor(Elephant elephant) {
        return "Elephant";
    }
}

Usando ((dynamic)this), informamos ao compilador que queremos que o this seja tratado como um tipo dinâmico, assim a existência de um método GenusFor com os parâmetros informados não será verificada em tempo de compilação.

Em tempo de execução, o CLR irá procurar por um método chamado GenusFor no objeto this e encontrará 4 sobrecargas, 1 pública e 3 privadas. Nesses casos, o comportamento do CLR é utilizar o método cujos tipos dos parâmetros esperados sejam o mais próximos possíveis dos parâmetros passados. Isso faz com que o método correto seja invocado, conforme o tipo de IAnimal recebido como parâmetro.

Interessante, não? No entanto lembre-se que recursos poderosos como esse devem ser usados com muita cautela. Brinque um pouco com o código disponível no GitHub e veja o impacto positivo e negativo que esse tipo de abordagem pode trazer.

Confira também o uso desse recurso em um dos exemplos citados no livro Implementing Domain-Driven Design, de Vaugh Vernon.

Abraços.