RTTI - Run Time Type Information

02/04/2006

Olá Senhores, como vai?

Estou com uma dúvida cruel.. e é por causa desta dúvida que não estou conseguindo terminar meu framework de persistência em Delphi.


Estou precisando capturar as informações contidas em pripriedades de um objeto.

Para quem nunca viu isso, veja o seguinte exemplo:

coloque um componente Button1

E no evento onclick coloque:

var
PropInfo: PPropInfo;
begin
PropInfo := GetPropInfo(Button1.ClassInfo, ´Caption´);
ShowMessage (GetStrProp (Button1, PropInfo);
end;

O resultado será um ShowMessage contendo o conteúdo que está
no caption do Button1. Até aí tudo bem, porém quando eu troco
o objeto Button1 por um objeto de uma classe minha (ex. Classe TPessoa), na hora de capturar o conteúdo através do GetStrProp, ele dá um erro de acesso na memória.

O exemplo seria mais ou menos assim:

var
PropInfo: PPropInfo;
Pessoa: TPessoa;
begin
Pessoa := TPessoa.Create;
//atribuo um valor para uma propriedade chamada Nome
Pessoa.Nome := ´Daniel´;
//tento capturar o conteúdo que está no objeto Pessoa, dentro da
//propriedade ´Nome´ (que tinha que ser ´Daniel´)
PropInfo := GetPropInfo(Pessoa.ClassInfo, ´Nome´);
//Quando irei mostrar o conteúdo dá erro de memória
ShowMessage (GetStrProp (Pessoa, PropInfo);
end;

Não sei qual é a diferença do Objeto Button para o Objeto Pessoa, pois ambos são objetos e herdam da classe TObject.

Alguém poderia me responder essa dúvida?

Um cordial abraço,

Daniel


Netcrusher

Respostas

02/04/2006

Marco Salles

isto é uma caso para o massuda .. Mas eu posso palpitar , afinal nas duvidas a gente aprende tb..
Quem sabe ´ele´ vem corrigindo algo que esta preso em mim . Se eu não botar para fora eu vou morrer sem saber

Pelo pouco que eu sei sobre o assunto eu vejo algumas coisas..

1)eu não sei qual o delphi que voce trabalha , mas a partir do delphi 5.0
ja existem rotinas mais sofisticadas , sem a necessidade de recuperar
o ponteiro GetPropInfo e aplicar uma das funçoes de acesso: GetStrProp

por exemplo

var 
PropInfo: PPropInfo; 
begin 
PropInfo := GetPropInfo(Button1.ClassInfo, ´Caption´); 
ShowMessage (GetStrProp (Button1, PropInfo); 

Pode ser substituido por simplesmente:

showmessage(GetPropValue (button1,´caption´);


2)Não sei qual é a diferença do Objeto Button para o Objeto Pessoa, pois ambos são objetos e herdam da classe TObject.

Sim , so que o obejto Button tb herda da TComponent e tem propriedades publicadas(PuBlished) , e essas tecnicas são aplicadas a propriedades publicadas e não simplesmente ha métodos de uma classe
de uma classe que voce definiu

Teste este exemplo:

procedure TForm1.Button1Click(Sender: TObject);
var
//PropInfo: PPropInfo;
Pessoa: TPessoa;
begin
Pessoa := TPessoa.Create;
//atribuo um valor para uma propriedade chamada Nome
Pessoa.Nome := ´Daniel´;
//tento capturar o conteúdo que está no objeto Pessoa, dentro da
//propriedade ´Nome´ (que tinha que ser ´Daniel´)
if IsPublishedProp (Pessoa,´Name´) then
   Showmessage(GetPropValue (Pessoa,´Name´))
else
  Showmessage(´Nada a apresentar´);

if IsPublishedProp (Button1,´Name´) then
   showmessage(GetPropValue (Button1,´Name´))
else
  Showmessage(´Nada a apresentar´);
end;


3)voce não deve trocar o polimorfismo e outras tecnicas de acesso a propriedades pelos métodos da Unit TypInfo(RTTI)


Responder Citar

02/04/2006

Netcrusher

Olá Marcos, valeu pela tentativa, porém, encontrei a solução, e nesse caso, é a única.

Para se trabalhar com o RTTI, os objetos devem herdar da classe TComponent, pois está especificada na biblioteca da RTTI. Isso não sou eu quem está dizendo, e sim a própria documentação do RTTI.

O que eu fiz foi um FrameWork que persiste um Objeto no banco de dados.

O interessante é que ele persiste qualquer tipo de objeto que seja derivada da classe TComponent.

Eu sei que fica muito estranho dizer que um Objeto de negócio herda da classe TComponent, porém, a solução funcionou.

Valeu pela tentativa..

Um cordial abraço,

Daniel


Responder Citar

03/04/2006

Marco Salles

Olá Marcos, valeu pela tentativa, porém, encontrei a solução, e nesse caso, é a única.


Para se trabalhar com o RTTI, os objetos devem herdar da classe TComponent, pois está especificada na biblioteca da RTTI. Isso não sou eu quem está dizendo, e sim a própria documentação do RTTI.


[b:6f76c742eb]e o que eu disse .. Foi diferente[/b:6f76c742eb] ????? :?: :?: :?:

[b:6f76c742eb]Sim , so que o obejto Button tb herda da TComponent [/b:6f76c742eb]e tem propriedades publicadas(PuBlished) , e essas tecnicas são aplicadas a propriedades publicadas e não simplesmente ha métodos de uma classe


[b:6f76c742eb]Disse a voce que alem de Button ser um tobject ele Herda da TComponent... [/b:6f76c742eb]

[b:6f76c742eb]Acho que voce não leu direitinho[/b:6f76c742eb] :cry: :cry: :cry: :cry:

Porem . disse alem.. Disse que alem de ter que derivar da TComponent esses métodos , são aplicados somente a propriedades Publisheds...
desses objetos derivados da TComponent.. veja o exemplo :

Type
 Botao =Class(TButton)
 public
  MinhaPropriedade : String;
end;

var
myBotao:TBotao;

begin
MyBotao:=TBotao.create(self);
MyBotao.MinhaPropriedae:=´Não é Piublished´;
showmessage(GetPropValue (Mybotao,´MinhaPropriedae´));
end;


[b:6f76c742eb]Não ira funcionar , apresar de obedecer teoricamente a condição de derivar da TComponent[/b:6f76c742eb]


Responder Citar

03/04/2006

Netcrusher

Opa Marcos, entendi sim... talvez eu não soube me expressar direito.

Porém, mesmo que em uma classe do gênero de negócio como TPessoa, possuindo seus métodos de acesso através dos properties - property (read and write) sendo publisheds, o RTTI não consegue capturar. Eu tentei fazer com que ele capturasse sem que o objeto TPessoa herdasse de TComponente, mas não funcionou (mesmo tendo seus métodos de acesso publicados - published).

Mas é isso aí..

Um abraço


Responder Citar

03/04/2006

Marco Salles

Eu tentei fazer com que ele capturasse sem que o objeto TPessoa herdasse de TComponente, mas não funcionou (mesmo tendo seus métodos de acesso publicados - published).


Mas voce registrou esse componente :?: :?: , isto é essas propriedades podem ser visualizadas no Objecto inspector de um objeto do tipo TPessoa????
Porque acho que so nesse casso , voce pode persistir os dados usando os métodos anteriores....


Responder Citar

03/04/2006

Netcrusher

Não é necessário registrar o Objeto do tipo TComponent..

A única coisa que eu fiz foi declarar que a classe TPessoa herda de TComponent:

Type
Tpessoa = Class (TComponent)

Bom.. se esse te pessoa fosse um objeto registrado (aparecendo na palheta de componentes) o object Inspector com certeza poderia visualizar os atributos e métodos.

Só pra exclarescer mais a minha idéia... é o seguinte...

Através do RTTI, podemos pegar uma classe e capturar todas as propriedades existentes (ex. NOme, Endereço, Bairro, etc.). E tmb, através do RTTI, conseguimos capturar todos os valores existentes no objeto, através de seus atributos.

Então o que o framewrk faz é, persistir um objeto, sem a necessidade de se utilizar seus get´s, e nem fazer referência para um tipo único de classe.

Não sei se vc entendeu...

Tipow.. a coisa é simples... porém... foi difícil de fazer.

Um forte abraço Marcos..


Responder Citar

03/04/2006

Marco Salles

nesse disse me disse estamos quase chegando a um denominador comum

Só pra exclarescer mais a minha idéia... é o seguinte... Através do RTTI, podemos pegar uma classe e capturar todas as propriedades existentes (ex. NOme, Endereço, Bairro, etc.). E tmb, através do RTTI, conseguimos capturar todos os valores existentes no objeto, através de seus atributos.


isto eu sei...

Então o que o framewrk faz é, persistir um objeto, sem a necessidade de se utilizar seus get´s, e nem fazer referência para um tipo único de classe.

So que é mais lento e so e recomendavel quando não se puder aplicar polimorfismo ou operadores is e as

Não é necessário registrar o Objeto do tipo TComponent..


isto eu confesso que não sabia ...

A única coisa que eu fiz foi declarar que a classe TPessoa herda de TComponent:


Pois é ... eu tinha te dito anteriormente que Para se trabalhar com o RTTI,[b:cde22b2bf0] os objetos devem herdar da classe TComponent[/b:cde22b2bf0], isto a gente concorda , porem ja tinha feito o teste abaixo < Igualzinho como voce esta se referindo >


Type 
Tpessoa = Class (TComponent) [/quote&93;
public
nome:String;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
pessoa:TPessoa;
begin
pessoa:=TPessoa.create(self);
pessoa.Nome:=´Não esto uconseguindo´;
showmessage(GetPropValue (pessoa,´nome´));
end;


[b:cde22b2bf0]Mas dá erro [/b:cde22b2bf0], logo deduzi que alem de derivar da[b:cde22b2bf0] TComponenent [/b:cde22b2bf0], seria necessário registrar o componente...Mas voce esta dizendo que dá certo :cry: :cry: :cry: ..[b:cde22b2bf0] Então aonde eu estou errando amigo [/b:cde22b2bf0] :cry: :cry:


Responder Citar

03/04/2006

Netcrusher

Olá Marcos.. a estrutura de um Objeto meu está assim:

Ex.:

type TPessoa = class (TComponent)
private
//atributos do objeto Pessoa
strNome : String;
protected
//Get´s
function getNome : String;
// Set´s
procedure setNome ( strNome : string );

//declaração das propriedades públicas de acesso
public
constructor Create;
destructor Destroy;
//propriedades públicadas
published
property Nome : string read getNome write setNome;
end;



Em seguida, é só fazer os get´s e sets.... e Jaúra...


Não existe nenhuma declaração pra registrar o Componente (Register)...

É uma programação Orientada a Componentes (porém.. tudo é objetos)...

Ele persiste componentes do gênero de negócio (business)..

Pra vc listar os atributos.. vc pode fazer assim:

var
Count, Loop: Integer;
List: TPropList;
begin
Count := GetPropList(TypeInfo(TPessoa), tkProperties, @List);
Listbox1.Items.BeginUpdate;
for Loop := 0 to Pred(Count) do
Listbox1.Items.Add(List[Loop]^.Name);
Listbox1.Items.EndUpdate;


Para acessar já seria outro método (já comentado nesse nosso diálogo).

É isso aí...

Um abraço Marcos..


Um cordial abraço,

Daniel


Responder Citar

05/04/2006

Marco Salles

esse nosso embate é importante para que a gente possa crescer nas diferenças..

Voltemos ao meu primeiro tópico:

Sim , so que o obejto Button tb herda da TComponent e tem propriedades publicadas(PuBlished) , e essas tecnicas são aplicadas a propriedades publicadas e não simplesmente ha métodos de uma classe


[b:4a9495d1c2][color=darkred:4a9495d1c2]eu disse no primeiro típico que era necessário herdar da TComponent e ainda assim estar na secção Published[/color:4a9495d1c2][/b:4a9495d1c2]

so que nesse tópico que lhe mandei , voce me [b:4a9495d1c2]desacreiditou[/b:4a9495d1c2]... :cry: :cry:

Olá Marcos, valeu pela tentativa....

Para se trabalhar com o RTTI, os objetos devem herdar da classe TComponent,



[b:4a9495d1c2][color=darkred:4a9495d1c2]Nisso eu returquei , novamente dizendo que não basta so derivar da TComponent , era preciso estar definido na secção Published[/color:4a9495d1c2][/b:4a9495d1c2]

Porem . disse alem.. Disse que alem de ter que derivar da TComponent esses métodos , são aplicados somente a propriedades Publisheds...


e novamente voce me [b:4a9495d1c2]desacreditou[/b:4a9495d1c2]...

Eu tentei fazer com que ele capturasse sem que o objeto TPessoa herdasse de TComponente, mas não funcionou (mesmo tendo seus métodos de acesso publicados - published).


Ai voce me deixou confuso :cry: :cry: ... e nesse momento eu desviei o foco da discusão... e ao ler esse tópico fiz confusão , porque achei que voce tinha derivado da tcomponent e tinha dado errado :cry: :cry:

[b:4a9495d1c2]Ai eu disse ´sem testar´ que era necessario Registar o componente[/b:4a9495d1c2]

essa foi a unica informação [b:4a9495d1c2]ERRADA[/b:4a9495d1c2] que lhe passei , depois de duas certas e voce[b:4a9495d1c2] desacreditando as duas.. [/b:4a9495d1c2]
E ai o tópico caiu em credibilidade e perdeu seu obejetivo porque eu fiquei todo confuso.
Hoje com mais calma parei para reler o tópico.E não encontrei nada Errado nos primeiros tópicos enviados e sim antevendo o que hoje voce ja sabe

Por fim um cordial abraço....


Responder Citar