Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 02-06-2016
elrayo76 elrayo76 is offline
Miembro
 
Registrado: ene 2004
Ubicación: En la tierra, por eso mis archivos en la tierra y no en la nuebe...
Posts: 290
Poder: 21
elrayo76 Va por buen camino
Usando RTTI para devolver lista de eventos

Intentando usar RTTI, no puedo encontrar una forma que me devuelva una lista con todos los eventos que pueda tener una clase.

He mirado las units del propio entorno de Delphi (XE8) y no hay nada que se de forma directa. Lo que he encontrado que dentro de la unit System.RTTI existe la clase TRttiType que contiene los métodos GetMethods, GetFields, GetProperties, GetIndexedProperties entre otros.

Mi pregunta ahora es la siguiente. ¿Puede ser que GetMethods devuelva todos los métodos de una clase, incluidos los que se usan para los evntos. Si es asi, como identifico cuales son los de los eventos, cuales son procedimientos, funciones, constructor, etc.?

Como dije antes, en la unit correspondiente no he visto nada que me de una idea de como hacer lo que quiero. ¿Acaso tendre que identificar cada uno de ellos por lo que diga delante (procedure, function, constructor, etc)?

Si alguien sabe como hacerlo y tiene algún ejemplo que me pueda orientar se los agradecería mucho. Ya saben cualquier cosa que algo no se entienda pueden preguntar y sera aclarado.

Saludos,
El Rayo
__________________
Si tienes una función o procedimiento con diez parámetros, probablemente hayas olvidado uno
Responder Con Cita
  #2  
Antiguo 02-06-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Al parecer, los eventos en Delphi son identificados mediante TTypeKind.tkMethod

Entonces, podes hacer esto:

Código Delphi [-]
uses
  Rtti;

procedure TForm1.Button1Click(Sender: TObject);
var
  c: TRttiContext;
  &Type: TRttiType;
  Prop: TRttiProperty;
begin
  Memo1.Clear;
  &Type := c.GetType(TButton);
  for Prop in &Type.GetProperties do
  begin
    if Prop.PropertyType.TypeKind = TTypeKind.tkMethod then
      Memo1.Lines.Add(Prop.ToString);
  end;
end;

Salida:

Código Delphi [-]
property OnClick: TNotifyEvent
property OnContextPopup: TContextPopupEvent
property OnDragDrop: TDragDropEvent
property OnDragOver: TDragOverEvent
property OnDropDownClick: TNotifyEvent
property OnEndDock: TEndDragEvent
property OnEndDrag: TEndDragEvent
property OnEnter: TNotifyEvent
property OnExit: TNotifyEvent
property OnKeyDown: TKeyEvent
property OnKeyPress: TKeyPressEvent
property OnKeyUp: TKeyEvent
property OnMouseActivate: TMouseActivateEvent
property OnMouseDown: TMouseEvent
property OnMouseEnter: TNotifyEvent
property OnMouseLeave: TNotifyEvent
property OnMouseMove: TMouseMoveEvent
property OnMouseUp: TMouseEvent
property OnStartDock: TStartDockEvent
property OnStartDrag: TStartDragEvent
property OnDropDownClick: TNotifyEvent
property WindowProc: TWndMethod
property OnGesture: TGestureEvent
Responder Con Cita
  #3  
Antiguo 02-06-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Otra opción que les servirá también a los que disponen de versiones mas viejitas:
Código Delphi [-]
uses TypInfo;

procedure GetMethodNames(AComponent: TComponentClass; TS: TStrings);
var
  i   : Integer;
  pInf: PPropList;
begin
  for i := 0 to GetPropList(AComponent.ClassInfo, pInf)-1 do
    if pInf[i].PropType^.Kind = tkMethod then
      TS.Add(Format('%s: %s',[pInf[i].Name, pInf[i].PropType^.Name]));
end;

// Ej. de uso
...
begin
   GetMethodNames(TListBox, ListBox1.Items); 
   ...

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #4  
Antiguo 02-06-2016
elrayo76 elrayo76 is offline
Miembro
 
Registrado: ene 2004
Ubicación: En la tierra, por eso mis archivos en la tierra y no en la nuebe...
Posts: 290
Poder: 21
elrayo76 Va por buen camino
Primero que nada, gracias por las respuestas. En cuanto pueda vere las dos opciones que me dan, ya que esto me servirá para hacer que el Framework pueda hacer lo mismo en versiones nuevas y mas viejas.

Saludos,
El Rayo
__________________
Si tienes una función o procedimiento con diez parámetros, probablemente hayas olvidado uno
Responder Con Cita
  #5  
Antiguo 02-06-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Hola Daniel, acabo de probar tu ejemplo en Delphi 2010 y funciona bien

Simplemente no entiendo porque limitas la clase a inspeccionar a que sea heredero de TComponent

Segun las pruebas que he hecho, funciona bien si heredamos de TObject:


Código Delphi [-]
  TCustomEvent = procedure of object;

  TMyClass = class
  private
    FEvento: TNotifyEvent;
    FEventoCustom: TCustomEvent;
    procedure SetEvento(const Value: TNotifyEvent);
    procedure SetEventoCustom(const Value: TCustomEvent);
  published
    property Evento: TNotifyEvent read FEvento write SetEvento;
    property EventoCustom: TCustomEvent read FEventoCustom write SetEventoCustom;
  end;

implementation

uses
  TypInfo;

procedure GetMethodNames(AClass: TClass; TS: TStrings);
var
  I: Integer;
  pInf: PPropList;
begin
  for I := 0 to GetPropList(AClass.ClassInfo, pInf) - 1 do
    if pInf[i].PropType^.Kind = tkMethod then
      TS.Add(Format('%s: %s', [pInf[i].Name, pInf[i].PropType^.Name]));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TS: TStrings;
begin
  TS := TStringList.Create;
  try
    GetMethodNames(TMyClass, TS);
    ShowMessage(TS.Text);
  finally  
    TS.Free;
  end;
end;

En este caso imprime tanto el TNotifyEvent como el TCustomEvent. Eso si, fue necesario declarar las propiedades como publicadas
Responder Con Cita
  #6  
Antiguo 02-06-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por AgustinOrtu Ver Mensaje
Simplemente no entiendo porque limitas la clase a inspeccionar a que sea heredero de TComponent
De hecho podría limitarlo a TPersistent, pero no más arriba, al menos en Delphi 7. O, mejor dicho, habría que verificar que AClass.ClassInfo no sea nil, y no lo será siempre que la directiva {$M+} esté presente, cosa que sucede con TPersistent.

Tú ejemplo, da un Access Violation en D7 hasta que se activa la directiva. No sé si en D 2010 se active siempre.

LnieComment Saludos
Responder Con Cita
  #7  
Antiguo 02-06-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Ahh buen dato roman, no estaba al tanto de esos detalles

Como elrayo habla de un framework lo primero que se me ocurrió es que quizá exigir pertenecer a la rama de TComponent como algo no deseable; de seguro el ya tiene armada sus jerarquías.

Aún así, es bueno saber que con agregar la directiva {M+} funciona bien. Una solución bastante sencilla podría ser incluir ese switch para las clase ancestro del framework
Responder Con Cita
  #8  
Antiguo 03-06-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

En Delphi 7 no le veo mucho sentido remontar mas allá de TComponent por que por ejemplo el código:
Código Delphi [-]
{$M-}  // (también funciona) 

procedure GetMethodNames(AClass: TClass; TS: TStrings);
var
  I: Integer;
  pInf: PPropList;
begin
  if not Assigned(AClass) then Exit;
  for I := 0 to GetPropList(AClass.ClassInfo, pInf) - 1 do
    if pInf[i].PropType^.Kind = tkMethod then
      TS.Add(Format('%s: %s', [pInf[i].Name, pInf[i].PropType^.Name]));
end;
no generará error si envío como argumento un objeto auxiliar:
Código Delphi [-]
   GetMethodNames(TStringList, Memo1.Lines);
pero tampoco mostrará los eventos OnChange y OnChanging de la clase enviada.

En este momento no imagino el caso, pero tal vez exista algún caso para el que convenga declarar el parámetro de tipo TPersistent.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....

Última edición por ecfisa fecha: 03-06-2016 a las 02:25:42.
Responder Con Cita
  #9  
Antiguo 03-06-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por ecfisa Ver Mensaje
no generará error si envío como argumento un objeto auxiliar:
No genera error porque aun cuando pones {$M-}, le pasas una clase que fué compilada con la directiva {$M+} y por tanto generó RTTI, y si pones {$M+} entes de la rutina de todas formas fallará si le pasas un clase compilada con {$M-}. Es decir, el valor de la directiva no cambiará de último momento lo que ya haya sido compilado.

Definitivamente, una rutina como la que escribiste necesita comprobar que ClassInfo no sea nil.

Ahora bien, si sólo vas a trabajar con clases de la VCL, ciertamente no tiene caso ir más allá de TComponent, pero no sabemos qué clase de framework esté trabajando y es posible que defina su propia jerarquía de clases independiente de la VCL.

LineComment Saludos
Responder Con Cita
  #10  
Antiguo 03-06-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Cita:
Definitivamente, una rutina como la que escribiste necesita comprobar que ClassInfo no sea nil.
Si el parámetro es declarado de tipo TClass, claramente es así.

Cita:
Ahora bien, si sólo vas a trabajar con clases de la VCL, ciertamente no tiene caso ir más allá de TComponent
Correcto.
Cita:
, pero no sabemos qué clase de framework esté trabajando y es posible que defina su propia jerarquía de clases independiente de la VCL.
Pero... ¿ funciona RTTI sobre una jerarquía propia (que no descienda de TObject) en Delphi 7 ?, te pregunto por que ciertamente lo desconozco.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #11  
Antiguo 03-06-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por ecfisa Ver Mensaje
Pero... ¿ funciona RTTI sobre una jerarquía propia (que no descienda de TObject) en Delphi 7 ?
Todo desciende de TObject. Pero puedes tener jerarquías que no tengan nada que ver con TPersistent -la clase base de la VCL- y que estén compiladas con {$M+} y generarán RTTI.

LineComment Saludos
Responder Con Cita
  #12  
Antiguo 03-06-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Ahora entendí a que te referías, había comprendido otra cosa por jerarquía propia (de ahí mi sorpresa y pregunta)

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....

Última edición por ecfisa fecha: 03-06-2016 a las 06:56:07.
Responder Con Cita
  #13  
Antiguo 03-06-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Si siguen así, voy a volver a participar como en los viejos tiempos, intentando aportar con tan buen ánimo como ustedes. ¡Qué gusto es leerles!
Responder Con Cita
  #14  
Antiguo 03-06-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Resurjamos como el ave Fénix

LineComment Saludos
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
funcion postgres para devolver nombre del mes banthas PostgreSQL 4 28-12-2015 22:14:28
Llenar una lista desplegable usando ibase MAXIUM PHP 2 12-03-2013 16:44:54
Monitor de eventos usando una clase dario61081 Trucos 5 08-02-2013 16:49:41
función date para devolver Nº dia de la semana lucasarts_18 PHP 2 27-03-2007 14:27:03
problema para devolver 2 valores en una funcion tiagor64 OOP 4 06-05-2005 15:38:59


La franja horaria es GMT +2. Ahora son las 17:03:37.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi