Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - GetPropList: ClassInfo ist nil
baka0815 - Di 06.07.10 12:03
Titel: GetPropList: ClassInfo ist nil
Hallo zusammen,
ich möchte alle
published-Eigenschaften eines Objekts herausfinden. Der folgende Code funktioniert allerdings nicht, weil der ClassInfo-Pointer
nil ist. Wenn ich statt des markierten Codes die Zeile darüber verwende, funktioniert es problemlos.
Woran liegt das? Das Objekt das ich übergebe ist von
TInterfacedObject abgeleitet und implementiert ein Interface. Aber auch wenn ich
TObject.Create übergebe ist ClassInfo
nil.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function GetProperties(Obj: TObject): TStringList; var Count, Loop: Integer; List: TPropList; begin Result := TStringList.Create; Count := GetPropList(PTypeInfo(Obj.ClassInfo), tkAny, @List);
Result.BeginUpdate; for Loop := 0 to Pred(Count) do Result.Add(List[Loop]^.Name); Result.EndUpdate; end; |
BenBE - Di 06.07.10 12:30
Also bei mir tut
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function GetProperties(Obj: TObject): TStringList; var Count, Loop: Integer; List: TPropList; begin Result := TStringList.Create; Count := GetPropList(PTypeInfo(Obj.ClassInfo), tkAny, @List);
Result.BeginUpdate; for Loop := 0 to Pred(Count) do Result.Add(List[Loop]^.Name); Result.EndUpdate; end; |
ohne Probleme (grad im Debugger nachgeschaut. Wobei: Deine TStringList ist nicht wirk,ich gegen Fehler geschützt. Try ... Except drum und im Fehlerfalle nil zurückgeben wäre praktisch ...
baka0815 - Di 06.07.10 13:09
Hmm, woran könnte das denn liegen? Wenn ich
GetProperties(TObject.Create) aufrufe - Speichermanagement, etc. ist erst einmal egal, da es nur Testcode ist - dann wird mir in
GetProperties angezeigt, dass
Obj.ClassInfo ein
nil-Pointer ist.
Ich habe mir dafür sicherheitshalber den Code von dir raus kopiert.
Die Funktion ClassInfo macht bei mir folgendes:
Delphi-Quelltext
1:
| Result := PPointer(Integer(Self) + vmtTypeInfo)^; |
Ich habe schon versucht, das so nachzustellen. Ich bekomme auch eine Adresse (
PPointer(Integer(Self) + vmtTypeInfo)), wenn ich diese mit
^ dereferenziere, bekomme ich aber wieder
nil -> stellt sich mir die Frage warum...
BenBE - Di 06.07.10 13:17
TObject hat keine published-Properties. Du brauchst eine Klasse, die von TPersistent abgeleitet ist.
Hab es it TApplication probiert.
baka0815 - Di 06.07.10 14:05
Wenn ich TPersistent.Create statt TObject.Create verwende funktioniert alles bestens, also müssen auch meine Klassen entsprechend geändert werden und nicht mehr von TInterfacedObject, sondern von TInterfacedPersistent erben, korrekt?
Zumindest funktioniert das ganze so.
Gibt es für dieses Verhalten (Interface != Objekt, TObject != TPersistent) einen vernünftigen Grund?
BenBE - Di 06.07.10 17:21
Ja ;-) Und der ist sogar dokumentiert ;-)
TObject ist im Status $H- compiliert und besitzt damit keine Typen-Informationen. Erst TPersistent ODER alle davon abgeleiteten Klassen besitzen diese. Für eigene, von TObject abgeleitete Klassen, kann man den $H+-Status aber auch manuell setzen.
Mehr Details dazu in der System.pas bei der Deklaration von TPersistent ...
guinnes - Mi 07.07.10 13:09
baka0815 hat folgendes geschrieben : |
| Und da meine Klasse published-Eigenschaften besitzt, bekomme ich die Info dass {$M+} für RTTI hinzugefügt wird und trotzdem funktioniert es nicht wenn ich von TObject (bzw. TInterfacedObject) ableite - von TPersistent (bzw. TInterfacedPersistent) funktioniert. |
Published macht doch erst ab TPersistent Sinn, da TObject das Streaming-System von Delphi noch nicht unterstützt
baka0815 - Mi 07.07.10 14:13
Ich brauche das Streaming-System ja eigentlich nicht und ich möchte die Klassen auch nicht serialisieren oder ähnliches, sondern nur per RTTI auf die Eigenschaften zugreifen. Ich finde es eh komisch, dass eben nur auf die published Eigenschaften zugegriffen werden kann (bin da von Java verwöhnt).
BenBE - Mi 07.07.10 14:19
Jup, meinte $M; brauch die so selten ;-)
TPersistent implementiert das Streaming-System, das ist richtig. TPErsistent ist aber auch die erste Klasse, die Property-Typinfos besitzt (eben wegen diesem Schalter).
Für andere Klassen werden zwar die Published-Properties als Properties generiert, der Streaming-Mechanismus funktioniert aber nicht, weil eben die erweiterten Klassen-Infos nicht erzeugt werden
Wenn Du deine eigene Ableitung auch im Status $M+ generierst, sollte es auch mit einer von TObject abgeleiteten Klasse gehen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!