Essa rotina só funciona em um método declarado na seção published, correto?

Em 19 de julho de 2010 20:27, Roni Rodrigo <ronirodr...@yahoo.com.br>escreveu:

>
>
> cara... eu utilizo a RTTI pra fazer chamadas a métodos da classe...
> para manipular os métodos e propriedades eu utilizo helpers para as
> classes da RTTI... se eu não me engano funciona com os métodos de
> qualquer escopo (ou menos da strict private.. não tenho certeza)... na
> verdade esse código eu achei na internet.. no site da embarcadero
> mesmo... mas agora não consegui achar pra passar o link.. então vou
> colocar o exemplo de como eu utilizo aqui....
>
> -------------------------------
> Uses TypInfo, ObjAuto, uRClassProperties;
> type
>
> // declara os helpers para a RTTI
> TParamInfoHelper = record helper for TParamInfo
> public
> function AsString: string;
> function NextParam: PParamInfo;
> end;
>
> TReturnInfoHelper = record helper for TReturnInfo
> public
> function AsString: string;
> end;
>
> TMethodInfoHeaderHelper = record helper for TMethodInfoHeader
> private
> function GetReturnInfo: PReturnInfo;
> public
> property ReturnInfo: PReturnInfo read GetReturnInfo;
> end;
>
> TObjectHelper = class helper for TObject
> public
> function RTTIMethodsAsString: string;
> end;
>
> function DescriptionOfMethod( Obj: TObject; MethodName: string ): string;
>
> implementation
>
> uses
> SysUtils;
>
> const
> SHORT_LEN = sizeof(ShortString) - 1;
>
> function DescriptionOfMethod( Obj: TObject; MethodName: string ): string;
> var
> header: PMethodInfoHeader;
> headerEnd: Pointer;
> Params, Param: PParamInfo;
> returnInfo: PReturnInfo;
> begin
> header := ObjAuto.GetMethodInfo( Obj, MethodName );
> if Header.Len <= SizeOf(TMethodInfoHeader) - SHORT_LEN +
> Length(Header.Name) then
> begin
> Result := 'No rich RTTI';
> exit;
> end;
> headerEnd := Pointer(Integer(header) + header^.Len);
> Params := PParamInfo(Integer(header) + SizeOf(header^) - SHORT_LEN +
> SizeOf(TReturnInfo) + Length(header^.Name));
> Param := Params;
> Result := '';
> while Integer(Param) < Integer(headerEnd) do
> begin
> Result := Result + Param.AsString + '; ';
> Param := Param.NextParam;
> end;
> Delete( Result, Length(Result)-1,2 );
> returnInfo := header.ReturnInfo;
> if assigned( returnInfo.ReturnType ) then
> Result := Format( 'function %s( %s ): %s', [ MethodName, Result,
> returnInfo.AsString ] )
> else
> Result := Format( 'procedure %s( %s )%s', [ MethodName, Result,
> returnInfo.AsString ] );
> end;
>
> { TParamInfoHelper }
>
> function TParamInfoHelper.AsString: string;
> begin
> Result := '';
> if pfResult in Flags then exit;
> Result := Name + ': ' + ParamType^.Name;
> if pfVar in self.Flags then
> Result := 'var ' + Result;
> end;
>
> function TParamInfoHelper.NextParam: PParamInfo;
> begin
> Result := PParamInfo(Integer(@self) + SizeOf(self) - SHORT_LEN +
> Length(Name));
> end;
>
> { TMethodInfoHeaderHelper }
>
> function TMethodInfoHeaderHelper.GetReturnInfo: PReturnInfo;
> begin
> Result := PReturnInfo(Integer(@self) + SizeOf(TMethodInfoHeader) -
> SHORT_LEN + Length(Name));
> end;
>
> { TReturnInfoHelper }
>
> function TReturnInfoHelper.AsString: string;
> var
> c: string;
> begin
> Assert( Version = 1, 'Version of ReturnInfo incorrect' );
> if assigned( ReturnType ) then
> Result := ReturnType^.Name;
> Result := Result + ';';
> case CallingConvention of
> ccRegister: ;// Default
> ccCdecl: c := 'cdecl';
> ccPascal: c := 'pascal';
> ccStdCall: c := 'stdcall';
> ccSafeCall: c := 'safecall';
> end;
> if c <> '' then Result := Result + ' ' + c + ';';
> end;
>
> { TObjectHelper }
>
> function TObjectHelper.RTTIMethodsAsString: string;
> var
> MethodInfo: Pointer;
> Count: Integer;
> method: PMethodInfoHeader;
> i: Integer;
> begin
> MethodInfo := PPointer(Integer(PPointer(self)^) + vmtMethodTable)^;
> if MethodInfo <> nil then
> begin
> Count := PWord(MethodInfo)^;
> Inc(Integer(MethodInfo), 2);
> method := MethodInfo;
> for i := 0 to Count - 1 do
> begin
> Result := Result + DescriptionOfMethod(self, method.Name) +
> sLineBreak;
> Inc(Integer(method), PMethodInfoHeader(method)^.Len);
> end;
> end;
> end;
>
> ----------------------------------------------------------
>
> feito isso, adicione essa unit a Uses que irá fazer as chamadas... e
> utilize normalmente os métodos da RTTI....
> para recuperar as informacoes do objeto em um TreeView, por exemplo:
>
> ---
> procedure GenerateNodes(Obj: TObject; Node: TTreeNode);
> var
> i: byte;
> InternalNode1, InternalNode2, InternalNode3: TTreeNode;
> PropList: PPropList;
> PropListCount: byte;
> MethodInfo: Pointer;
> MethodListCount: byte;
> Method: PMethodInfoHeader;
> begin
> if Assigned(Node) then
> InternalNode1 := Node
> else
> InternalNode1 := TreeView1.Items.Add(nil, Obj.ClassName);
> //Propriedades
> InternalNode2 := TreeView1.Items.AddChild(
> InternalNode1, 'Propriedades');
> PropListCount := GetPropList(Obj, PropList);
> for i := 0 to Pred(PropListCount) do
> begin
> InternalNode3 := TreeView1.Items.AddChild(InternalNode2,
> string(PropList[i].Name) + '=' +
> QuotedStr(
> string(
> GetPropValue(
> Obj,
> string(Proplist[i].Name)
> )
> )
> )
> );
> if PropType(Obj, string( PropList[i].Name )) = tkClass then
> GenerateNodes(GetObjectProp(Obj, string(PropList[i].Name)),
> InternalNode3);
> end;
> //Métodos
> InternalNode2 := TreeView1.Items.AddChild(InternalNode1, 'Métodos');
> //MethodInfo contera toda a lista metodos encontrada na area da vmt
> //referente ao objeto passado no caso abaixo a variavel Obj
> MethodInfo := PPointer(Integer(PPointer(Obj)^) + vmtMethodTable)^;
> if MethodInfo <> nil then
> begin
> //Retorna a qtd de metodos encontrados
> MethodListCount := PWord(MethodInfo)^;
> Inc(Integer(MethodInfo), 2);
> method := MethodInfo;
> for i := 0 to Pred(MethodListCount) do
> begin
> TreeView1.Items.AddChild(InternalNode2, string( Method.Name ));
> Inc(integer(Method), PMethodInfoHeader(Method)^.Len);
> end;
> end;
> end;
>
> -----------------
>
> crie uma função para executar o método:
>
> function ExecMethod(AObj: TObject; AMethodName: string; // objeto e nome
> do Metodo
> const ParamIndexes: array of Integer; // indice de
> parametros
> const Params: array of Variant): Variant; // valor
> dos parametros
> var
> Method: PMethodInfoHeader;
> begin
> try
> Method := GetMethodInfo(AObj, ShortString(AMethodName));
> if Assigned( Method ) then
> Result := ObjectInvoke(AObj, Method, ParamIndexes, Params);
> finally
> end;
> end;
>
> ---------------
>
> para invocar um método, vc passa teu objeto, o nome do método e
> possiveis parametros, por exemplo:
>
> var
> Nome: string;
> begin
> Nome := VarToString(ExecMethod(AObj: TObject; 'getNomeCompleto',
> [], []);
> ShowMessage(Nome);
>
> ---------------------
> se não estiver conseguindo recuperar o método, tenta usar a diretiva
> METHODINFO na declaracao das tuas classes:
>
> {$M+} ou {$METHODINFO ON}
> TClasse = class
> end;
> {$M-} ou {$METHODINFO OFF}
>
> divirta-se ai... hehehe... espero q ajude....
>
> o/
>
> Em 19/07/2010 16:18, eric_developer escreveu:
>
> > Não consegui resolver e vou deixar isso de lado.
> > Talvez o delphi não permita (mesmo me parecendo tão ilógico) ou é uma
> > caixa preta até mesmo para uma lista de quase 5000 pessoas.
> >
> > Obrigado aquelas que tentaram ajudar, há uns dias o Bruno da
> > Embarcadero disse que era possivel, espero que um dia nos mostre como
> > rsrs, e que não seja nada que dependa do Delphi 2010 ou 2020.
> >
> > Grato,
> > Eric
> >
> > --- Em delphi-br@yahoogrupos.com.br <delphi-br%40yahoogrupos.com.br>
> > <mailto:delphi-br%40yahoogrupos.com.br<delphi-br%2540yahoogrupos.com.br>>,
> "eric_developer"
> > <developer.syst...@...> escreveu
> > >
> > > Boa tarde pessoal,
> > >
> > > alguem sabe como obter o ponteiro de métodos existentes ? no
> > exemplo, se eu criar o método "teste" para o form2, funciona,
> > retornando o ponteiro.
> > >
> > > No lugar de form2, usarei componentes edit, combobox, etc e metodos
> > existentes.
> > >
> > > myCallMethod( edit1, 'SETFOCUS' ) ;
> > > myCallMethod( form3, 'SETFOCUS' ) ;
> > >
> > > procedure TForm2.teste ;
> > > begin
> > > ShowMessage('OLA');
> > > end;
> > >
> > >
> > > procedure TForm2.Button1Click(Sender: TObject);
> > > var
> > > routine : TMethod ;
> > > Begin
> > >
> > > routine.data:=pointer(form2) ;
> > > routine.Code:=Form2.MethodAddress('teste') ; // Nome do metodo
> > > if routine.Code <> nil then
> > > begin
> > > ShowMessage('OK');
> > > end;
> > >
> > > end;
> > >
> > > Grato,
> > > Eric Developer Systems
> > >
>
> [As partes desta mensagem que não continham texto foram removidas]
>
>  
>


[As partes desta mensagem que não continham texto foram removidas]



------------------------------------

-- 
<<<<< FAVOR REMOVER ESTA PARTE AO RESPONDER ESTA MENSAGEM >>>>>

<*> Para ver as mensagens antigas, acesse:
    http://br.groups.yahoo.com/group/delphi-br/messages

<*> Para falar com o moderador, envie um e-mail para:
    delphi-br-ow...@yahoogrupos.com.br
Links do Yahoo! Grupos

<*> Para visitar o site do seu grupo na web, acesse:
    http://br.groups.yahoo.com/group/delphi-br/

<*> Para sair deste grupo, envie um e-mail para:
    delphi-br-unsubscr...@yahoogrupos.com.br

<*> O uso que você faz do Yahoo! Grupos está sujeito aos:
    http://br.yahoo.com/info/utos.html


Responder a