[Delphi] Usando uma classe sem usá-la (?!)

Que título estranho para um artigo, não?
Vou explicar melhor essa antítese. Quando precisamos trabalhar com uma instância de uma classe, devemos referenciá-la na seção uses da unit, correto? Bom, mais ou menos. O objetivo deste artigo é apresentar uma forma de utilizar uma classe sem necessariamente adicionar a sua referência na unit. O nome dessa mágica é RTTI!

André, RTTI de novo?

Sim! Apenas para esclarecer, pessoal: o RTTI é um universo de possibilidades. É bem provável que ainda haverá outros artigos sobre este tópico aqui no blog. A ideia é explorar, aos poucos, a capacidade deste recurso para demonstrar as vantagens que podemos obter com a sua utilização.

A biblioteca de RTTI do Delphi disponibiliza um record chamado TRttiContext, do namespace System.Rtti. Por meio deste, ganhamos acesso às estruturas das classes que compõem o projeto. Para isso, utilizamos o método GetType informando o tipo como parâmetro, exemplificado no código abaixo:

Além do GetType, o record TRttiContext também fornece o método FindType para encontrar um tipo existente pelo nome, porém, com uma ressalva: o parâmetro deve vir acompanhado do nome da unit. Veja o exemplo a seguir:

Exemplo

Vamos adiante. Para demonstrar essa funcionalidade, decidi abordar um exemplo prático.

Considere a simples unit a seguir, que declara uma classe com um único método para abrir o bloco de notas:

Notou algo de incomum? A instrução no initialization, não é?

Pois bem, como a classe não é referenciada em outras units, o linker do Delphi tende a ignorá-la na produção do executável. Neste caso, obviamente, o método FindType do TRttiContext não será capaz de encontrá-la, portanto, adicionei uma simples instrução na seção initialization (um workaround) para que ela possa considerada pelo linker.

Agora, em outra unit, chamaremos o método dessa classe sem precisar referenciá-la na seção uses. Acredita ou não? 🙂

Para que isso seja possível, utilizaremos o GetMethod (para encontrar o método pela descrição) e o Invoke (para executar o método) das classes TRttiInstanceType e TRttiMethod, respectivamente.

Procedure de um objeto executado pelo Invoke do RTTI

Agora você pode acreditar! 😀

E se for necessário passar parâmetros?

Sem problemas! Na chamada do método Invoke, observe a presença dos colchetes. Dentro dele, podemos informar os parâmetros do método que será executado. Vamos ver como funciona?

Em TMinhaClasse, haverá um novo método, bem simples, para somar dois valores:

Em seguida, faremos o mesmo procedimento: executar o método da classe sem referenciar a unit.

O código é basicamente o mesmo apresentado acima, salvo que, dessa vez, informamos os parâmetros ao invocar o método. Como exemplo, indiquei os números 10 e 20 e optei por remover os comentários para facilitar a leitura:

Function de um objeto executado pelo Invoke do RTTI

 

Impressionante, não?

Faça proveito deste recurso do RTTI para criar bibliotecas de chamadas ou para evitar dependências explícitas entre units. Além disso, é um ótimo aliado ao se trabalhar com Generics.

Fico por aqui, leitores! Volto em breve com o próximo artigo da série sobre Design Patterns!
Abração!


 

André Celestino