Abfragen von Typinformationen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Mit RTTI arbeiten


Einführung

Der Anfangspunkt jeder RTTI-Arbeitssitzung ist das Ermitteln der Typinformationen. In Delphi werden Typinformationen nur für Typen und globale Unit-Routinen, -Konstanten oder -Variablen ausgegeben. Das bedeutet, dass mit dem ermittelten TRttiContext nur Informationen über die deklarierten Typen abgefragt werden können.

Es gibt drei grundlegende Methoden zum Ermitteln von Informationen über einen Typ:

  • Abrufen einer Liste aller in der Anwendung deklarierten Typen.
  • Abrufen von Informationen für einen bestimmten Typ anhand des Typinformations-Handles oder des qualifizierten Namens.
  • Abfragen von Typen in individuellen Laufzeit-Packages mit den beiden ersten Methoden.

Abrufen aller Typen

Mit der Methode TRttiContext.GetTypes können Sie eine Liste aller in einer Anwendung deklarierten Typen ermitteln. Die Methode listet alle öffentlich (public) sichtbaren Typen (diejenigen, die im interface-Abschnitt von Units deklariert sind) auf und gibt ein Array mit TRttiType-Objekten zurück. Jedes TRttiType-Objekt stellt für den Zugriff auf die Informationen über den Typ, den es beschreibt, eine High-Level-API bereit:

var
    LContext: TRttiContext;
    LType: TRttiType;
begin
    { Den RTTI-Kontext ermitteln }
    LContext := TRttiContext.Create;

    { Alle in der Anwendung deklarierten Typen auflisten }
    for LType in LContext.GetTypes() do
        Writeln(LType.Name);

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Den RTTI-Kontext ermitteln
    TRttiContext *context = new TRttiContext();

    // Alle in der Anwendung deklarierten Typen auflisten
    DynamicArray<TRttiType*>typeArray = context->GetTypes();
    for (int i = 0; i < typeArray.Length; i++) {
        TRttiType *type = typeArray[i];
        printf("%ls\n", type->Name.c_str());
    }

    delete context;
    return 0;
}

Das obige Beispiel ermittelt den RTTI-Kontext und ruft dann damit die Liste aller öffentlich verfügbaren Typen ab. Die for-Schleife gibt die Namen der Typen in der Konsole aus.

Die TRttiType-Instanzen sollten nicht vom Entwickler bereinigt werden. Wie im vorherigen Thema beschrieben, ist TRttiContext für die Verwaltung der Lebensdauer zuständig.

Abrufen von Informationen für einen bestimmten Typ

Wenn der Name des Typs, über den Informationen zur Laufzeit abgerufen werden sollen, zur Compilierzeit bekannt ist, enthält TRttiContext zwei weitere Methoden:

  • TRttiContext.GetType: ermittelt Typinformationen für ein gegebenes System.TypInfo.PTypeInfo-Handle. Das PTypeInfo-Handle wird zur Compilierzeit mit dem Operator TypeInfo abgerufen.
  • TRttiContext.FindType: sucht die Typinformationen anhand des qualifizierten Typnamens. Der qualifizierte Typname besteht aus zwei Komponenten: Unit-Name, der durch einen Punkt vom Typnamen getrennt wird (z.B. Classes.TStrings).

Das folgende Beispiel zeigt die Verwendung dieser Methoden:

var
    LContext: TRttiContext;
    LType: TRttiType;

begin
    { Den RTTI-Kontext ermitteln }
    LContext := TRttiContext.Create;

    { Typinformationen für Integer ermitteln }
    LType := LContext.GetType(TypeInfo(Integer));
    Writeln(LType.Name);

    { Typinformationen für einen Typ in der Unit Classes ermitteln }
    LType := LContext.FindType('Classes.TStrings');
    if not LType.IsInstance then
        Writeln('Expected TStrings to be a class!');

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Den RTTI-Kontext ermitteln
    TRttiContext *context = new TRttiContext();

    // Typinformationen für Integer ermitteln
    TRttiType *type = context->GetType(__delphirtti(Integer));
    printf("%ls\n", type->Name.c_str());

    type = context->FindType("Classes.TStrings");
    if ((type->IsInstance) == false) {
        puts("Expected TStrings to be a class!");
    }

    delete context;
    return 0;
}

Normalerweise sind die Methoden GetType und FindType zur Laufzeit hilfreich, wenn der Name des Typs oder das PTypeInfo-Handle indirekt ermittelt wird.

Package-Informationen

TRttiContext stellt die spezielle Methode TRttiContext.GetPackages bereit, mit der alle aktuell in der Anwendung (einschließlich des Hauptanwendungsmoduls, das auch als Package gilt) geladenen Laufzeit-Packages aufgelistet werden können. GetPackages gibt ein Array mit TRttiPackage-Instanzen zurück. Die Instanzen stellen eine Reihe von Funktionen zum Ermitteln der in dem Package deklarierten Typen bereit:

var
    LContext: TRttiContext;
    LType: TRttiType;
    LPackage: TRttiPackage;

begin
    { Den RTTI-Kontext ermitteln }
    LContext := TRttiContext.Create;

    { Das zweite Package (rtl140) abrufen }
    LPackage := LContext.GetPackages()[1];

    { Alle im Package rtl140 deklarierten Typen auflisten }
    for LType in LPackage.GetTypes() do
        Writeln(LType.Name);

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Den RTTI-Kontext ermitteln
    TRttiContext *context = new TRttiContext();

    // Das zweite Package (rtl140) abrufen
    DynamicArray<TRttiPackage*>packageArray = context->GetPackages();
    TRttiPackage *package = packageArray[1];

    // Alle im Package rtl140 deklarierten Typen auflisten
    DynamicArray<TRttiType*>typeArray = package->GetTypes();
    for (int i = 0; i < typeArray.Length; i++) {
        TRttiType *type = typeArray[i];
        printf("%ls\n", type->Name.c_str());
    }

    delete context;
    return 0;
}

Das obige Beispiel ruft Informationen über das als zweites geladene Package (in diesem Fall rtl140.bpl) ab und ermittelt dann alle Typen, die von diesem Package bereitgestellt werden. Beachten Sie bitte, dass das Beispiel mit Laufzeit-Packages erzeugt werden muss; ansonsten werden die Typen direkt in der Anwendung erzeugt.

Wie TRttiContext ermöglicht TRttiPackage das Ermitteln des Typs anhand seines qualifizierten Namens:

var
    LContext: TRttiContext;
    LType: TRttiType;
    LPackage: TRttiPackage;

begin
    { Den RTTI-Kontext ermitteln }
    LContext := TRttiContext.Create;

    { Das zweite Package (rtl140) abrufen }
    LPackage := LContext.GetPackages()[1];

    { Typinformationen für die Klasse TStrings abrufen }
    LType := LPackage.FindType('Classes.TStrings');
    Writeln(LType.Name);

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Den RTTI-Kontext ermitteln
    TRttiContext *context = new TRttiContext();

    // Das zweite Package (rtl140) abrufen
    DynamicArray<TRttiPackage*>packageArray = context->GetPackages();
    TRttiPackage *package = packageArray[1];

    // Typinformationen für die Klasse TStrings abrufen
    TRttiType *type = package->FindType("Classes.TStrings");
    printf("%ls\n", type->Name.c_str());

    delete context;
    return 0;
}

Siehe auch