RTTI (Run-Time Type Information) no Delphi

RTTI (Run-Time Type Information) é uma técnica utilizada para identificar tipo de objetos armazenados em memória em tempo de execução.

Abaixo um exemplo de como utilizar RTTI em sua aplicação, este exemplo é apenas uma idéia de como usar RTTI para criar classes e métodos genêricos de acesso a base de dados.

O primeiro código é de uma classe genêrica de modelo da estrutura da tabela no banco de dados. Note que a mesma herda da classe TPersistent pois nela existe as directivas de compilação {$M+} ({$METHODINFO ON}) e {$M-} ({$METHODINFO OFF}) necessárias para implementar o acesso dos dados em memória.

TModel.pas
1
2
3
4
5
6
7
8
9
10
11
type
TModel = class(TPersistent)
private
{ Private declarations }

public
{ Public declarations }
constructor Create(); virtual;
destructor Destroy(); override;

end;

O segundo código é de uma classe de modelo da estrutura da tabela Pessoa do banco de dados, note que ela herda a classe TModel e que suas propridades estão declaradas na sessão published pois assim é possível acessa-lás em tempo de execução.

TModelPessoa.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type
TModelPessoa = class(TModel)
private
{ Private declarations }
FPessIden: Integer;
FPessNome: String;

public
{ Public declarations }
constructor Create(); override;
destructor Destroy(); override;

published
{ Published declarations }
property PessIden: Integer read FPessIden write FPessIden;
property PessNome: String read FPessNome write FPessNome;

end;

O terceiro código é de uma classe teria os métodos de operação na base de dados porém eu retirei pois este não é o foco deste post e sim apenas mostrar uma utilização do RTTI. Então vamos a explicação, o método fillProperty é responsável por verificar as propriedades do objeto do tipo ou que herde a classe TModel passado por parâmetro. Outro detalhe importante é a declaração da unit TypInfo que contém os métodos responsáveis em acessar os dados em memória.

TController.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
uses
TypInfo, Dialogs, Classes, Model;

type
TController = class(TObject)
private
{ Private declarations }

public
{ Public declarations }
constructor Create(); virtual;
destructor Destroy(); override;
procedure fillProperties(model: TModel);

end;

Como descrito anteriomente o método responsável por acessar os dados em memória do objeto em tempo de execução. Note que após o termino do for foi inserido um ShowMessage(msg.Text); para informar ao usuário as propriedades e o valor das propriedades do objeto passado por parâmetro.

TController.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
procedure TController.fillProperties(model: TModel);
var
listProp: PPropList;
listPropCount, i: Integer;
propInfo: TPropInfo;
valueProp: Variant;
msg: TStringList;
begin
{Obtem informacoes dos atributos que sao Publisheds}
listPropCount:= GetPropList(model.ClassInfo, tkAny, nil);
GetMem(listProp, listPropCount * SizeOf(TPropInfo));

try
msg:= TStringList.Create();

GetPropList(model, listProp);
for i:= 0 to Pred(listPropCount) do
begin
{Obtem informacoes da propriedade}
propInfo:= TPropInfo(listProp^[i]^);
valueProp:= GetPropValue(model, propInfo.Name);

msg.Add(Format('%s: %s;', [propInfo.Name, valueProp]));
end;

ShowMessage(msg.Text);
finally
FreeAndNil(msg);
FreeMem(listProp);
end;
end;

E por fim um trecho de código para você adicionar ao evento de um button por exemplo de como utilizar o método fillProperties da classe TController.

TController.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var
modelPessoa: TModelPessoa;
controller: TController;
begin
try
modelPessoa:= TModelPessoa.Create();
controller := TController.Create();
modelPessoa.PessIden:= StrToInt(self.edtPessIden.Text);
modelPessoa.PessNome:= self.edtPessNome.Text;

controller.fillProperties(modelPessoa);
finally
FreeAndNil(modelPessoa);
FreeAndNil(controller);
end;
end;

Espero que gostem e seja útil de alguma forma este exemplo. Em breve estárei postando uma aplicação mais real da utilização do RTTI para criação de classes e métodos genêricos de acesso a dados, lembrando que este não é a única utilização do RTTI.

Desde já agredeço a visita.