Einzelnen Beitrag anzeigen

Tobitoba

Registriert seit: 6. Jan 2017
7 Beiträge
 
Delphi 12 Athens
 
#1

RegisterClasses und RTTI - dynamisches Registrieren aller Klassen zur Laufzeit

  Alt 15. Okt 2018, 15:46
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])
Tobi
  Mit Zitat antworten Zitat