|
Usuários |
|
92 Usuários Online
|
|
[Artigos]
Conhecendo um pouco da RTTI – Parte V - Final |
Publicado por rboaro : Sexta, Janeiro 11, 2013 - 07:41 GMT-3 (422 leituras)
comentar Enviar para um amigo Versão para impressão
|
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 pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos. |
|
|
Edição 112 |
|
|
50 Programas Fontes |
|
|
Produtos |
|
|