Clique para saber mais...
  Home     Download     Produtos / Cursos     Revista     Vídeo Aulas     Fórum     Contato   Clique aqui para logar | 12 de Junho de 2026
  Login

Codinome
Senha
Salvar informações

 Esqueci minha senha
 Novo Cadastro

  Usuários
92 Usuários Online

  Revista ActiveDelphi
 Assine Já!
 Edições
 Sobre a Revista

  Conteúdo
 Apostilas
 Artigos
 Componentes
 Dicas
 News
 Programas / Exemplos
 Vídeo Aulas

  Serviços
 Active News
 Fórum
 Produtos / Cursos

  Outros
 Colunistas
 Contato
 Top 10

  Publicidade

  [Artigos]  Conhecendo um pouco da RTTI – Parte V - Final
Publicado por rboaro : Sexta, Janeiro 11, 2013 - 07:41 GMT-3 (422 leituras)
Comentários comentar   Enviar esta notícia a um amigo Enviar para um amigo   Versão para Impressão Versão para impressão
Diego Garcia Vamos chegando finalmente ao final deste estudo introdutório sobre a magnifica RTTI do todo poderoso Delphi. Neste post quero solucionar uma pequena pendencia que está presente em nosso estudo desde a primeira parte, quem está acompanhando desde o começo deve se lembrar do nosso método pegarValoresRTTIObj(), pra quem não se lembra, esse método basicamente listava todos os campos e valores de um determinado objeto, mas o que aconteceria, se um dos campos fosse um vetor, seja ele dinâmico ou estático? vamos ver:

type
TTeste = class
private
FArrayEstatico : Array[0..3] of Integer;
FArrayDinamico : Array of Integer;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
oTeste : TTeste;
I: Integer;
begin
oTeste := TTeste.Create;
try
for I := Low(oTeste.FArrayEstatico) to High(oTeste.FArrayEstatico) do
oTeste.FArrayEstatico[i] := i;

SetLength(oTeste.FArrayDinamico,4);
for I := low(oTeste.FArrayDinamico) to high(oTeste.FArrayDinamico) do
oTeste.FArrayDinamico[i] := i;

pegarValoresRTTIObj(oTeste,Memo1.Lines);
finally
oTeste.Free;
end;

Seguindo o padrão que utilizamos durante o estudo (um formulário com um TMemo e um TButton para teste), ao executar o método implementado no click do nosso Button1, BOOOOM, teríamos o erro Insufficient RTTI available to support this operation, confesso que pesquisei muito para tentar descobrir o que vem a ser realmente esse problema mas não consegui chegar a nenhuma resposta que tivesse uma real relação com nosso exemplo, porem ficou claro que isso ocorre devido ao uso do vetor estático, então para resolver esse problema, vamos criar um tipo que nada mais é do que um vetor estático.

Type
TArrayOfIntegerEstatio = Array[0..3] of Integer;

type
TTeste = class
private
FArrayEstatico : TArrayOfIntegerEstatio;
FArrayDinamico : Array of Integer;
end;

Após o pulo do gato acima, já é possível executar nosso método sem exceções, porem, o que vai ser apresentado no TMemo é realmente o que esperamos que nosso método faça? vejamos, o resultado da execução do método pegarValoresRTTIObj() vai ser

TTeste-FArrayEstatico=(array)
TTeste-FArrayDinamico=(dynamic array)

Bom, finalmente cheguei aonde eu queria chegar, imaginando que estaríamos em uma situação em que precisaríamos listar dinamicamente o valor de todos campos de um objeto utilizando a RTTI e este tivesse algum campo que fosse um vetor, já teríamos algum problema, mas o que seria do desenvolvimento de softwares se não existissem os desafios?
Vamos la, uma pequena adaptação no nosso método já é o suficiente, basta verificar se o campo é do tipo Array e caso seja, utilizando as possibilidades do poderoso TValue vamos extrair o valor de cada posições deste vetor.

procedure pegarValoresRTTIObj(objeto: TObject; linhasRetorno: TStrings);
var
fldRtti : TRttiField;
typRtti : TRttiType;
ctxRtti : TRttiContext;
I : Integer;
begin
ctxRtti := TRttiContext.create;
try
typRtti := ctxRtti.GetType(objeto.ClassType);

for fldRtti in typRtti.GetFields do
begin
if fldRtti.GetValue(objeto).IsObject then
pegarValoresRTTIObj(fldRtti.GetValue(objeto).AsObject,linhasRetorno)
else if fldRtti.GetValue(objeto).IsArray then //a partir daqui trato o vetor
begin
for I := 0 to fldRtti.GetValue(objeto).GetArrayLength - 1 do
linhasRetorno.Add(objeto.ClassName + '-' + fldRtti.Name + '[' + intToStr(i) +']=' + fldRtti.GetValue(objeto).GetArrayElement(i).ToString);
end
else
linhasRetorno.Add(objeto.ClassName + '-' + fldRtti.Name + '=' + fldRtti.GetValue(objeto).ToString);
end;
finally
ctxRtti.Free;
end;
end;

Repare que nos casos de campos vetores o método GetValue() do TRttiField ira nos retornar um TValue que está armazenando um vetor, sendo assim, podemos utilizar o método GetArrayElement() do TValue que retorna uma posição do vetor em questão também como um TValue tornando possível extrair o valor desta posição. Com essas alterações, o resultado do nosso método no cenário atual seria

TTeste-FArrayEstatico[0]=0
TTeste-FArrayEstatico[1]=1
TTeste-FArrayEstatico[2]=2
TTeste-FArrayEstatico[3]=3
TTeste-FArrayDinamico[0]=0
TTeste-FArrayDinamico[1]=1
TTeste-FArrayDinamico[2]=2
TTeste-FArrayDinamico[3]=3

Não é uma solução genérica definitiva porem, mostra de uma forma simples como trabalhar com vetores em rotinas que utilizam funcionalidades da RTTI. Como venho dizendo, existem milhões de possibilidades de uso da RTTI, como gerar um XML ou um JSON dinamicamente, construir um ORM, validações dinâmicas etc, basta utilizar um pouco da imaginação, vale ressaltar que também é possível acessar as informações de um record utilizando a RTTI, mas esse assunto fica para uma próxima oportunidade.


Comentários Comentários
   Ordem:  
Comentários pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos.
  Edição 112

Revista ActiveDelphi

  50 Programas Fontes


  Produtos

Conheça Nossos Produtos

Copyright© 2001-2016 – Active Delphi – Todos os direitos reservados