Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Propertys einer Componente für eine Klasse mittels RTTI (https://www.delphipraxis.net/131563-propertys-einer-componente-fuer-eine-klasse-mittels-rtti.html)

oki 26. Mär 2009 16:49


Propertys einer Componente für eine Klasse mittels RTTI
 
Hi,

kleines Problem. Ich kann die Propertys meiner Komponente mittels RTTI-Funktion GetPropList ermitteln. Dabei übergebe ich die Instanz meines Objectes sowie eine PropList und bekomme alle published Propertys zurückgeliefert.

Jetzt möchte ich aber nur die Propertys haben, die in einer bestimmten Basisklasse enthalten sind. Hier mal als Beispiel:
Delphi-Quellcode:
  TCustomClass = class(TComponent)
  published
    property Prop1;
  end;

  TBaseClass = class(TCustomClass)
  published
    property Prop2;
  end;

  TExpertClass = class(TBaseClass)
  published
    property Prop3;
  end;

.....

var MyClass : TExpertClass;
.....

  MyClass := TExpertClass.Create(nil);

  // alle Propertys für MyClass, die in TCustomClass enthalten sind auflisten
  ??????????
Also an der Stelle nur Prop1.

Einer ne Idee? Würd mich sehr freuen.

Bei GetPropInfo kann eine Klassentyp übergeben werden. Was das dann bringt ist mir noch nicht so richtig klar, leider geht das nicht mit GetPropList.
Ich hab auch irgentwie das Gefühl, das ich über GetTypeInfos da ran komme. Einen richtigen Plan hab ich aber nicht.

Schon mal Dank für eure Hilfe,

Gruß oki

himitsu 26. Mär 2009 16:58

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
im Notfall alle Properties ermitteln,
das Ganze nochmals bei der Parent-Klasse (wenn eine existiert)
und am Ende alles in der Parent-Klasse Enthaltene aus der andere Liste entfernen.

oki 26. Mär 2009 17:04

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Also ein TempObj der geforderten Klasse erstellen, die Props lesen, das TempObj frei geben und diese Propliste auf mein Objekt anwenden?

Die Idee ist mir auch schon gekommen, fand ich nur nicht so elegant. Dachte eher ich hab eine Bildungslücke (ok, hab ich sicher :mrgreen: ) und es gibt einen Weg, wie ich zum Lesen der PropList eine Klasse angeben kann.

Gruß oki

oki 26. Mär 2009 17:15

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Gehts vielleicht auch so?

Delphi-Quellcode:
var PropList : PPropList;
    PropCount : Integer;
    AClass : TClass;
begin
  AClass := GetClass('TCustomClass');
  if Assigned(AClass) then
    PropCount := GetPropList(AClass.ClassInfo, PropList);
  end;
end;
Gruß oki

oki 26. Mär 2009 17:18

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Boahh,

hat geklappt. Bin beeindrukt. Auch noch mal Dank an himitsu.

Gruß oki

himitsu 26. Mär 2009 17:19

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
wenn das geht, dann sollte das auch so gehn?
Delphi-Quellcode:
var PropList : PPropList;
    AClass : TClass;
begin
  AClass := TCustomClass;
  PropCount := GetPropList(AClass.ClassInfo, PropList);
end;

// bzw.

var PropList : PPropList;
begin
  PropCount := GetPropList(TCustomClass.ClassInfo, PropList);
end;

oki 26. Mär 2009 17:21

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Klar, sorry mein Fehler. Ich hab zu diesem Zeitpunkt nur den Namen der Klasse. Somit muss ich sie erst holen. Konntest du aber nicht wissen, da ich keinen Funktionskopf mitgeliefert hatte.

Passt aber.

Dank und Gruß

oki

himitsu 26. Mär 2009 17:26

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
ochso :stupid:

und was liefert GetPropList nun alles?

oki 26. Mär 2009 21:12

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Zitat:

Zitat von himitsu
ochso :stupid:

und was liefert GetPropList nun alles?

Alle Propertys meiner Komponente incl. Werte die unter der angegebenen Klasse definiert sind.

Gruß oki

himitsu 26. Mär 2009 22:24

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Delphi-Quellcode:
Uses Types, TypInfo;

Function GetClassPropList(C: TClass): TStringDynArray;
  Var L, L2:      PPropList;
    i, i2, i3, i4: Integer;

  Begin
    L := nil;
    L2 := nil;
    i := 0;
    i2 := 0;
    Try
      If Assigned(C) Then Begin
        i := GetPropList(C.ClassInfo, L);
        C := C.ClassParent;
        If Assigned(C) Then i2 := GetPropList(C.ClassInfo, L2);
      End;
      For i3 := 0 to i - 1 do
        For i4 := 0 to i2 - 1 do
          If Assigned(L[i3]) and (L[i3].Name = L2[i4].Name) Then L[i3] := nil;
      i4 := 0;
      For i3 := 0 to i - 1 do
        If Assigned(L[i3]) Then Inc(i4);
      SetLength(Result, i4);
      i4 := 0;
      For i3 := 0 to i - 1 do
        If Assigned(L[i3]) Then Begin
          Result[i4] := L[i3].Name;
          Inc(i4);
        End;
    Finally
      If Assigned(L) Then FreeMem(L);
      If Assigned(L2) Then FreeMem(L2);
    End;
  End;




Var C: TClass;
  R:  TStringDynArray;
  i:  Integer;

Begin
  C := TScrollingWinControl; //C := GetClass('TScrollingWinControl');
  R := GetClassPropList(C);
  For i := 0 to High(R) do Memo1.Lines.Add(R[i]);
End;
getestet und läuft :angel: ... nur GetClass findet die Klasse nicht :gruebel:

oki 27. Mär 2009 06:58

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Moin himitsu,

mit dem Lesen der Propertys hatte ich kein Problem. Es ging wirklich nur um den Fall, dass ich nicht alle Propertys der Klasse haben wollte, sondern nur die einer ausgewählten Vorfahrenklasse.

GetClass findet nur registrierte Klassen. Erstellst du eine eigene Klasse, auch als Nachfahre einer registrierten, so muss diese mit RegisterClass registriert werden. Dann findet GetClass diese auch.

Gruß oki

himitsu 27. Mär 2009 09:06

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
TPropInfo enhält zumindestens keine Info, wozu es gehört.
Man könnte hier höchstens nachsehn an welcher Stelle es liegt (wohin der jeweilige Pointer in PPropList zeigt), aber ich glaub es wäre keine ganz sichere Methode, anhand deren Position diese zuordnen zu wollen,
obwohl ja die List der Methoden der Klasse zusammenstehen sollten, in der jeweiligen Klassendefinition.

Nja, so läuft es doch auch.
(PS: ich Idiot hatte beim Testen TForm1 verwendet und mich gewundert, daß dort die Ergebnisliste leer war :nerd: )

Achso :oops: ... dachte irgendwie, der findet alle Persistent-Klassen (TPersistent und Nachfahre)

oki 27. Mär 2009 09:25

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
Zitat:

(PS: ich Idiot hatte beim Testen TForm1 verwendet und mich gewundert, daß dort die Ergebnisliste leer war Nerd )

Achso Embarassed ... dachte irgendwie, der findet alle Persistent-Klassen (TPersistent und Nachfahre)
Joop, den hab ich auch schon hinter mir. Willkommen im Club :mrgreen:

Gruß oki

himitsu 27. Mär 2009 13:43

Re: Propertys einer Componente für eine Klasse mittels RTTI
 
hab grad dort drüben noch was Nettes gefunden...

jetzt ist der Code etwas kürzer und übersichtlicher:
Delphi-Quellcode:
Uses Types, TypInfo;

Function GetClassPropList(C: TClass): TStringDynArray;
  Var L:      PPropList;
    i, i2, i3: Integer;

  Begin
    Result := nil;
    If not Assigned(C) Then Exit;
    L := nil;
    i := 0;
    Try
      i := GetPropList(C.ClassInfo, L);
      C := C.ClassParent;
      For i2 := i - 1 downto 0 do
        If IsPublishedProp(C, L[i2].Name) Then L[i2] := nil;
      i3 := 0;
      For i2 := i - 1 downto 0 do
        If Assigned(L[i2]) Then Inc(i3);
      SetLength(Result, i3);
      For i2 := i - 1 downto 0 do
        If Assigned(L[i2]) Then Begin
          Dec(i3);
          Result[i3] := L[i2].Name;
        End;
    Finally
      If Assigned(L) Then FreeMem(L);
    End;
  End;
und noch eine ganz Kurze/Übersichtliche ohne vorreservieren des Arrays:
Delphi-Quellcode:
Function GetClassPropList(C: TClass): TStringDynArray;
  Var L:      PPropList;
    i, i2, i3: Integer;

  Begin
    Result := nil;
    If not Assigned(C) Then Exit;
    L := nil;
    Try
      i := GetPropList(C.ClassInfo, L);
      For i2 := 0 to i - 1 do
        If not IsPublishedProp(C.ClassParent, L[i2].Name) Then Begin
          i3 := Length(Result);
          SetLength(Result, i3 + 1);
          Result[i3] := L[i2].Name;
        End;
    Finally
      If Assigned(L) Then FreeMem(L);
    End;
  End;


Aber ohne nachzusehn, würd ich einfach mal behaupten, die alte/allererste Funktion ist dagegen immerhin schneller :stupid:


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz