Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit (https://www.delphipraxis.net/198224-registerclasses-und-rtti-dynamisches-registrieren-aller-klassen-zur-laufzeit.html)

Tobitoba 15. Okt 2018 14:46

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])

Uwe Raabe 15. Okt 2018 15:50

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.

freimatz 16. Okt 2018 07:11

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.

hoika 16. Okt 2018 07:18

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.

Tobitoba 16. Okt 2018 08:01

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;

mcinternet 19. Jun 2019 15:16

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

Ralf Kaiser 19. Jun 2019 17:39

AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
 
Zitat:

Zitat von mcinternet (Beitrag 1435039)

Also beißt sich die Katze da in den Schwanz :shock:

Also - gibt es eine bessere Idee? :?:

Registriere die Klassen in ihren eigenen Units im
Delphi-Quellcode:
initialzation
Abschnitt.

BerndS 20. Jun 2019 07:25

AW: RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit
 
So was ähnliches wurde hier schon mal besprochen. Schau mal hier.
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 15:09 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