![]() |
RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
Hallo zusammen,
in unserem Projekt, müssen wir dafür sorgen, dass alle verfügbare Klassen des Projektes in den RegisterClasses registriert werden. Nun habe ich mich ein wenig mit RTTI und dessen Funktion GetTypes auseinander gesetzt. Leider erzielen wir bisher nur Teilziele. Im Projekt Quelltext, stehen rund 400 Klassen, welche beim Starten auch tatsächlich vor den Ausführen der nachfolgenden Funktion initialisiert werden, während die Funktion leider nur 146 relevante davon findet und registriert. Die Filterung nach "TFRM" liegt daran, dass wir explizit alle unsere Klassen die Relevant sind so vorab benennen. Nun das bestehende Problem der aktuellen Funktion: Klasse_A wird mittels der Funktion gefunden und wird in RegisterClasses registriert. Klasse_B wird nicht gefunden. Beide Klassen erben von Klasse_C, welche gefunden wird und verwenden die selben Uses. Um zu schauen, ob die fehlende Klasse_B überhaupt irgendwo aufgelistet wird ggf. mit dem Unit-Namen o.ä., habe ich mit alle Typen "KlassenALL" und alle Klassen "klassen" als Liste ausgeben lassen. Leider findet man in keiner der beiden die entschiedene fehlende Klasse_B. Habt Ihr eventuell Iden, Gedankenansätze, wieso das so sein könnte oder wo man nochmal nachschauen kann ? Weiterer Hinweis: wir wollen das manuelle Registrieren unter dem Block initialization vermeiden, da sonst ebenfalls die Implementierung der Units in den uses erfolgen muss. Durch die hohe Anzahl ist es serh mühselig und der Wartungsaufwand, sowie die Sicherstellung ist zu hoch. In dem Code-Beispiel, habe ich die Uses und initialization mal nur auf ein Beispiel herunter gebrochen. Verwendete Delphi-Version XE10 Seattle Architect Bei Fragen einfach melden, vielen Dank vorab :) Lg Tobi
Delphi-Quellcode:
uses System.Classes, System.Rtti, System.SysUtils;
procedure FindeAlleKlassen(); implementation uses fKlasseA procedure FindeAlleKlassen; var ctx: TRttiContext; typ: TRttiType; list: TArray<TRttiType>; i: Integer; KlassenAll: TStringList; Klassen: TstringList; begin // sucht die Klasse und gibt diese für das Array der RegisterClasses zurück. ctx := TRttiContext.Create; list := ctx.GetTypes; Klassen := TStringList.Create; Klassen.Clear; KlassenAll := TStringList.Create; KlassenAll.Clear; i := 0; for typ in list do begin //Zum Testen aller typen ohne Instanziierung KlassenALL.Add(typ.Name); if typ.IsInstance and not(typ = nil) then begin if Pos('TFRM',UpperCase(typ.ToString),1)>0 then begin //Zum testen in StringList schrieben und Inhalte nachlesen Klassen.Add(typ.AsInstance.MetaclassType.ClassName); //Füge die Klasse den RegisterClasses hinzu. RegisterClasses([TPersistentClass(typ.AsInstance.MetaclassType)]); //Zähler i Inc(i); end; end; end; // Testzwecke Klassen.SaveToFile('X:\Klassen.txt'); KlassenALL.SaveToFile('X:\KlassenALL.txt'); ctx.Free; end; initialization RegisterClasses([TfrmKlasseA]) |
AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
In der Regel entfernt der Linker allen Methoden und Klassen, die nicht benutzt werden. Diese sind dann logischerweise auch über RTTI nicht zu finden. Der RegisterClass-Aufruf für TfrmKlasseA sorgt dafür, daß diese Klasse und ihre Vorfahren benutzt werden. Deswegen wird TfrmKlasseA und TfrmKlasseC auch gefunden. Es ist gut möglich, daß deine Anforderung gar nicht realisierbar ist, wenn das RegisterClass die einzige Verwendung einer Klasse wäre.
|
AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
An das dachte ich auch.
Für den Zweck habe ich eine eigene unit, die nur dazu da ist alle solche units nach uses aufzuführen. |
AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
Hallo,
das uses nützt Dir aber nichts, weil der Linker erkennt, dass das Formular nicht benutzt wird. |
AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
Hey Uwe,
vielen lieben Dank für die erste rasche Antwort. Das Linken haben wir in dem Projekt eingeschaltet, sowie das Bereitstellen von der detaillierten map-Datei und drc-Datei. Leider sind hier auch Unterschiede wahrzunehmen. KlasseA steht dort mit der unit..Klasse drin und hat nachfolgend alle Inhalte aufgelistet unit.Funtkion, bei der KlasseB leider nur mit der .pas und .dfm ... Der letzte von dir beschriebene Fall , ist hier eigentlich nicht gegeben. Weiterer Unterschied ist, in den Projekt-Optionen > Formulare, dort werden nur die 3 wichtigen automatisch erzeugt und der Rest wird unter verfügbare Formulare kategorisiert. Verschiebe ich die fehlende Klasse auf die automatische Seite, ist diese über RTTI zu finden. Eine generelle Aussage dessen ist es aber nicht, da von den 147 gefunden nicht eine einzige auf dieser Seite steht. Von den Formularen die automatisch erzeugt werden, erbt auch keine einzige, diese sind völlig autark. Unabhängig der Seite, werden trotzdem vor der RTTI-Funktion alle Klassen initialisiert, ebenfalls die fehlende. Nochmals zum Zweck der Verwendung: Wir wissen anhand in einer DB stehenden Info, welches Formular geladen werden soll. Die Speicherung und Auslesung erfolgt als String. Im Anschluss wird der String an eine Funktion übergeben, die entsprechend die zu ladenden Formulare in einem Detaildialog des Hauptfensters einbettet und ggf. schon weitere Funktionen ausführt. Dafür verwenden wir die unten aufgelistete Funktion. Gruß Tobi
Delphi-Quellcode:
var
c: TFormClass; begin c := TFormClass(GetClass(Klasse:string)); DoShowListForm(c); end; |
AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
Hallo,
ich möchte es ähnlich machen. Dieses "FindeAlleKlassen" findet die Klassen allerdings erst, nachdem sie mit registerclass registriert sind. Vorher sind diese unsichtbar. Sie werden alle eincompiliert und ich hab ne Liste mit über 30 Klassen, welche ich ganz gern dynamisch registrieren möchte (dynamisch erzeugt werden sie ohnehin). Beispiel: unit registerforms uses Classes,...bla bla, uDummy; registerclass(TFrmDummy); ---------------- Unit HauptMenue wenn User = Recht auf TFrmDummy then xForm := TFrmDummy.create(self); ------------------ Wenn ich das FindeAlleKlassen aufrufe, um z.B. TFrmDummy und alle anderen zu registrieren, dann findet es nur TFrmMain. Rufe ich es NACH (an der Stelle mal "RegisterClasses([TPersistentClass(typ.AsInstance.MetaclassType)]);" auskommentiert) meinem "registerclass(TFrmDummy);" auf - dann wird TFrmDummy gefunden. Also beißt sich die Katze da in den Schwanz :shock: Also - gibt es eine bessere Idee? :?: Beste Grüße mcinternet |
AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
Zitat:
Delphi-Quellcode:
Abschnitt.
initialzation
|
AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
So was ähnliches wurde hier schon mal besprochen. Schau mal
![]() Ich verwende das etwas abgewandelt immer vor einem Release um zu prüfen, ob sich alle Formulare und Reports laden lassen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz