Informationen für strukturierte Typen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Mit RTTI arbeiten

Strukturierte Typen in Delphi haben weit mehr zugeordnete Informationen als einfache Typen. Dieses Thema erläutert detailliert die Typinformationen für strukturierte Typen.

Statische Arrays und dynamische Arrays

Statische Arrays (oder einfach Arrays) und dynamische Arrays werden nicht von demselben RTTI-Objekt beschrieben. TRttiArrayType wird für statische Arrays und TRttiDynamicArrayType für dynamische Arrays verwendet.

TRttiArray stellt die folgenden Eigenschaften bereit:

  • TotalElementCount: gibt die Gesamtanzahl der Elemente an, die von diesem Array in all seinen Dimensionen aufgenommen werden können.
  • ElementType: gibt die Typinformationen für die Array-Elemente an.
  • DimensionCount: gibt die Anzahl der Dimensionen an, die für dieses Array deklariert sind.
  • Dimensions: ist eine indizierte Eigenschaft, die die Typinformationen für den Typ zurückgibt, mit dem die Dimension bezeichnet wird (TRttiEnumerationType oder TRttiOrdinalType).

Die Eigenschaft Dimensions gibt die Typinformationen des Typs zurück, der die Indizes für eine Dimension bereitstellt. Sehen Sie sich das folgende Beispiel an:

type
    TMatrix = array [Boolean, 1 .. 10] of Integer;

var
    LContext: TRttiContext;
    LType: TRttiArrayType;
    LDimType: TRttiOrdinalType;
    LDimIndex: Integer;

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

    { Das RTTI-Objekt ermitteln }
    LType := LContext.GetType(TypeInfo(TMatrix)) as TRttiArrayType;

    { Alle Dimensionen auflisten }
    for LDimIndex := 0 to LType.DimensionCount - 1 do
    begin
        LDimType := LType.Dimensions[LDimIndex] as TRttiOrdinalType;
        Writeln('Dimension ', LDimIndex, ' = [', LDimType.MinValue, '..',
          LDimType.MaxValue, ']');
    end;

end.
// Kein C++-Quellcode verfügbar

TRttiDynamicArray stellt die folgenden Eigenschaften bereit:

  • ElementSize: gibt die Größe eines Elements im Array an.
  • ElementType: gibt die Typinformationen für die Array-Elemente an.
  • OleAutoVarType: gibt den OLE-Typ für die Array-Elemente an (sofern anwendbar).
  • DeclaringUnitName: gibt den Namen der Unit zurück, in dem das Array deklariert wurde.

Bei dynamischen Arrays ist alles etwas einfacher, weil dynamische Arrays keine Mehrfach-Dimensionen zulassen und keine vordefinierte Größe haben.

Klassen, Interfaces und Records

Strukturierte Typen, wie Klassen, Records und Interfaces verfügen neben den normalen Typinformationen über zusätzliche Informationen für ihre Member. Abhängig vom eigentlichen Typ werden einige Funktionen unterstützt, andere dagegen nicht:

Typ/Member

Felder

Methoden

Eigenschaften

Abstammung

Records

Ja

Ja

Nein

N/A

Klassen

Ja

Ja

Ja

Ja

Interfaces

N/A

Ja

N/A

Ja


Klassentypen werden von TRttiInstanceType-RTTI-Objekten, Record-Typen von TRttiRecordType-Objekten und Interfaces von TRttiInterfaceType-Objekten repräsentiert.

Bitte beachten Sie, dass - während nur diese drei Typen Methoden, Felder und Interfaces unterstützen -, sich die eigentlichen Methoden und Eigenschaften, die den Zugriff auf diese Typinformationen zulassen, in TRttiType befinden. Dies wurde so festgelegt, um den Abfragevorgang zu erleichtern. Die folgende Tabelle führt die wichtigsten Methoden und Eigenschaften auf, die mit diesen strukturierten Typen verwendet werden können:

Methoden

Beschreibung

Records

Klassen

Interfaces

GetField

Gibt ein bestimmtes Feld anhand des Namens zurück.

Ja

Ja

Nein

GetFields, GetDeclaredFields

Gibt eine Liste aller (oder nur der deklarierten) Felder des Typs zurück.

Ja

Ja

Nein

GetMethod

Gibt eine bestimmte Methode anhand des Namens zurück.

Nein

Ja

Ja

GetMethods, GetDeclaredMethods

Gibt eine Liste aller (oder nur der deklarierten) Methoden des Typs zurück.

Nein

Ja

Ja

GetProperty

Gibt eine bestimmte Eigenschaft anhand des Namens zurück.

Nein

Ja

Nein

GetProperties, GetDeclaredProperties

Gibt eine Liste aller (oder nur der deklarierten) Eigenschaften des Typs zurück.

Nein

Ja

Nein

BaseType

Gibt die Vorfahrklasse oder das Vorfahr-Interface zurück.

Nein

Ja

Ja


Das folgende Beispiel zeigt den Unterschied zwischen dem Ermitteln aller oder nur der deklarierten Member:

var
    LContext: TRttiContext;
    LClass: TRttiInstanceType;
    LNewMethods, LNewFields, LNewProperties: Integer;

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

    { Typinformationen für TStringList ermitteln }
    LClass := LContext.GetType(TStringList) as TRttiInstanceType;

    { Die Anzahl der neuen Methoden, Felder und Eigenschaften ermitteln, die in TStringList eingeführt wurden }
    LNewMethods := Length(LClass.GetMethods()) -
      Length(LClass.GetDeclaredMethods());
    LNewProperties := Length(LClass.GetProperties()) -
      Length(LClass.GetDeclaredProperties());
    LNewFields := Length(LClass.GetFields()) -
      Length(LClass.GetDeclaredFields());

    { Das Ergebnis in der Konsole ausgeben }
    Writeln(Format
      ('%s introduces %d fields, %d methods, and %d properties relative to its %s ancestor',
      [LClass.Name, LNewFields, LNewMethods, LNewProperties,
      LClass.BaseType.Name]));

    LContext.Free;

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

    // Typinformationen für TStringList ermitteln
    TRttiType *type = context->GetType(__delphirtti(TStringList));
    TRttiInstanceType *instanceType = dynamic_cast<TRttiInstanceType*>(type);
    if (!instanceType) {
        return 1; // Fehler bei der dynamischen Typumwandlung
    }

    // Die Anzahl der neuen Methoden, Felder und Eigenschaften ermitteln, die in TStringList eingeführt wurden
    const int newMethods = instanceType->GetMethods().Length -
        instanceType->GetDeclaredMethods().Length;
    const int newProperties = instanceType->GetProperties().Length -
        instanceType->GetDeclaredProperties().Length;
    const int newFields = instanceType->GetFields().Length -
        instanceType->GetDeclaredFields().Length;

    // Das Ergebnis in der Konsole ausgeben
    printf("%ls introduces %d fields, %d methods, and %d properties relative to its %ls ancestor"
        , instanceType->Name.c_str(), newFields, newMethods, newProperties,
        instanceType->BaseType->Name.c_str());

    delete context;
    return 0;
}

Konsolenausgabe:

TStringList introduces 11 fields, 68 methods, and 14 properties relative to its
TStrings ancestor.

Beachten Sie bitte, dass überschriebene Methoden auch als neu eingeführt gelten.

Siehe auch