Informationen für einfache Typen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Mit RTTI arbeiten

Einführung

In Delphi gibt es zwei grundlegende Kategorien für Typen: einfache Typen und strukturierte Typen. Im Allgemeinen verfügen einfache Typen über weit weniger Typinformationen als strukturierte Typen.

Mit der Eigenschaft TRttiType.TypeKind können Sie feststellen, ob der ermittelte TRttiType einem gegebenen Typ entspricht. Der Wert der Eigenschaft gibt den tatsächlichen Typ an. Eine weitere Methode zum Feststellen des tatsächlichen Klassentyps einer TRttiType-Instanz stellt der Operator is dar:

 { Nur String-Typen anzeigen } 
 for LType in LContext.GetTypes() do 
     if LType is TRttiStringType then 
         WriteLn(LType.ToString);
 // Nur String-Typen anzeigen
 DynamicArray<TRttiType*>typeArray = context->GetTypes();
 for (int i = 0; i < typeArray.Length; i++) {
     TRttiType *type = typeArray[i];
     TRttiStringType *stringType = dynamic_cast<TRttiStringType*>(type);
     if (stringType) {
         printf("%ls\n", stringType->ToString().c_str());
     }
 }

Das obige Beispiel zeigt nur die in der Anwendung und ihrer Packages deklarierten String-Typen an.

Ordinale Typen

Ordinale Typen werden von der Klasseninstanz TRttiOrdinalType beschrieben. TRttiOrdinalType stellt Eigenschaften, wie MinValue, MaxValue und OrdType, für den Zugriff auf die für ordinale Typen spezifischen Informationen bereit.

Das folgende Beispiel listet alle in der Anwendung oder ihren Packages definierten ordinalen Typen auf und gibt deren Eigenschaften in der Konsole aus:

    for LType in LContext.GetTypes() do
        if LType is TRttiOrdinalType then
        begin
            Writeln('Type name:', LType.Name);
            Writeln('Min allowed value:', TRttiOrdinalType(LType).MinValue);
            Writeln('Max allowed value:', TRttiOrdinalType(LType).MaxValue);
            Writeln;
        end;
    // Alle in der Anwendung deklarierten Typen auflisten
    DynamicArray<TRttiType*>typeArray = context->GetTypes();
    for (int i = 0; i < typeArray.Length; i++) {
        TRttiType *type = typeArray[i];
        TRttiOrdinalType *ordinalType = dynamic_cast<TRttiOrdinalType*>(type);
        if (ordinalType) {
            printf("%ls\n", ordinalType->ToString().c_str());
            printf("\t min value: %ld\n", ordinalType->MinValue);
            printf("\t max value: %ld\n", ordinalType->MaxValue);
        }
    }

Beachten Sie bitte, dass Aufzählungstypen auch als ordinale Typen behandelt werden. Daher gibt das obige Beispiel auch die Informationen für diese Typen aus.

64-Bit-Integer-Typen

64-Bit-Integer-Typen verwenden nicht denselben Basistyp wie ordinale Typen. Daher werden 64-Bit-Integer-Typen von der Klasse TRttiInt64Type beschrieben. TRttiInt64Type stellt - vergleichbar mit TRttiOrdinalType - die Eigenschaften MinValue und MaxValue bereit.

Das folgende Beispiel listet alle in der Anwendung oder ihren Packages deklarierten 64-Bit-Integer-Typen auf:

    for LType in LContext.GetTypes() do
        if LType is TRttiInt64Type then
        begin
            Writeln('Type name:', LType.Name);
            Writeln('Min allowed value:', TRttiInt64Type(LType).MinValue);
            Writeln('Max allowed value:', TRttiInt64Type(LType).MaxValue);
            Writeln;
        end;
    DynamicArray<TRttiType*>typeArray = context->GetTypes();
    for (int i = 0; i < typeArray.Length; i++) {
        TRttiType *type = typeArray[i];
        TRttiInt64Type *int64Type = dynamic_cast<TRttiInt64Type*>(type);
        if (int64Type) {
            printf("type name: %ls\n", int64Type->ToString().c_str());
            printf("\t min allowed value: %Ld\n", int64Type->MinValue);
            printf("\t max allowed value: %Ld\n", int64Type->MaxValue);
        }
    }

Gleitkommatypen

Gleitkommatypen werden von der Klasseninstanz TRttiFloatType beschrieben. TRttiFloatType stellt nur die Eigenschaft FloatType bereit, mit der der Untertyp des Gleitkommatyps ermittelt werden kann.

Das folgende Beispiel gibt alle deklarierten Gleitkommatypen aus, deren Untertyp Double ist:

for LType in LContext.GetTypes() do
  if (LType is TRttiFloatType) and (TRttiFloatType(LType).FloatType = ftDouble) then
    Writeln('Type name:', LType.Name);

In dem ausgegebenen Ergebnis sind neben dem Typ Double auch der Typ Real, der ein double-Typ ist, sowie in der Unit System deklarierte Datums-/Zeittypen enthalten.

Mengentypen

Mengentypen werden von der Klasseninstanz TRttiSetType beschrieben. TRttiSetType stellt nur die Eigenschaft ElementType bereit, die Typinformationen für die Elemente enthält, aus denen die Menge besteht. Für eine als

type
  TByteSet = set of Byte;

definierte Menge gibt der folgende Code den Typnamen der Elementmenge (Byte) aus:

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

  { TRttiSetType für den Typ ermitteln } 
  LType := LContext.GetType(TypeInfo(TByteSet)) as TRttiSetType;

  { Den Typnamen der Elementmenge ausgeben } 
  WriteLn('The elements of the set are of ', LType.ElementType.Name, ' type.'); 
end.

Aufzählungstypen

Aufzählungstypen werden von der Klasseninstanz TRttiEnumerationType beschrieben. TRttiEnumerationType ist von TRttiOrdinalType abgeleitet und fügt die neue Eigenschaft UnderlyingType hinzu. UnderlyingType stellt Typinformationen für den tatsächlichen Aufzählungstyp bereit, der in diesem Aufzählungstyp verwendet wird.

Sehen Sie sich das folgende Beispiel mit zwei Aufzählungstypen an, einem neuen und einem, der ein Alias der Standardaufzählung TSeekOrigin ist:

type
  TNewEnum = (neOne, neTwo, neThree);
  TOtherEnum = type TSeekOrigin;

Der folgende Code gibt den Namen des zugrunde liegenden Typs für beide Typen aus:

  { Die Typinformationen für beide Typen ermitteln } 
  LType1 := LContext.GetType(TypeInfo(TNewEnum)) as TRttiEnumerationType; 
  LType2 := LContext.GetType(TypeInfo(TOtherEnum)) as TRttiEnumerationType;
 
  { Die Typnamen der zugrunde liegenden Typen ausgeben } 
  WriteLn('Underlying type for TNewEnum is ', LType1.UnderlyingType.Name); 
  WriteLn('Underlying type for TOtherEnum is ', LType2.UnderlyingType.Name);

Bitte beachten Sie, dass die Eigenschaft UnderlyingType für neu deklarierte Aufzählungstypen (z.B. TNewEnum) die Typinformationen für den Aufzählungstyp selbst zurückgibt. Bei Typen mit starkem Alias (wie z.B. TOtherEnum) gibt UnderlyingType die Typinformationen für diesen Typ zurück.

String-Typen

String-Typen werden von der Klasseninstanz TRttiStringType beschrieben. TRttiStringType stellt nur die Eigenschaft StringKind bereit, mit der der tatsächliche String-Typ ermittelt werden kann. Der String-Typ kann Folgendes sein:

  • Kurzer String
  • Ansi-String
  • Wide-String
  • Unicode-String

Das folgende Beispiel gibt alle in der Anwendung oder ihren Packages deklarierten ANSI-String-Typen aus:

for LType in LContext.GetTypes() do
  if (LType is TRttiStringType) and (TRttiStringType(LType).StringKind = skAnsiString) then
    Writeln(LType.Name);

Für AnsiString-Typen ist in der Unit RTTI eine spezielle TRttiAnsiStringType-Klasse definiert. TRttiAnsiStringType ist von TRttiStringType abgeleitet und fügt die neue Eigenschaft CodePage hinzu, mit der die Codeseite des AnsiString ermittelt werden kann.

Das folgende Beispiel gibt die Codeseite des Typs RawByteString aus:

{ Typinformationen für RawByteString (ist ein AnsiString) ermitteln } 
LType := LContext.GetType(TypeInfo(RawByteString)) as TRttiAnsiStringType; 
WriteLn('The codepage of the string is ', LType.CodePage);

Klassenreferenzen (Metaklassen)

Klassenreferenzen werden von der Klasseninstanz TRttiClassRefType beschrieben. Mit TRttiClassRefType kann der Klassentyp ermittelt werden, der als Basis der durch die Metaklasse (mit der Eigenschaft InstanceType) angegebenen Hierarchie verwendet wird. TRttiClassRefType ermöglicht über MetaclassType auch den direkten Zugriff auf die Metaklasse selbst.

Das folgende Beispiel gibt alle Metaklassentypen aus, die in der Anwendung oder ihren Packages deklariert sind; sie stellen Typen dar, die von TComponent abgeleitet sind:

var 
  LContext: TRttiContext; 
  LType: TRttiType; 
  LMeta: TRttiClassRefType; 

begin 
  { Den RTTI-Kontext ermitteln } 
  LContext := TRttiContext.Create;
  
  { Alle Typen abrufen, die Klassenreferenzen sind und deren Klasse von TComponent abstammt } 
  for LType in LContext.GetTypes() do 
    if (LType is TRttiClassRefType) then 
    begin 
      { Den Rtti-Typ umwandeln } 
      LMeta := TRttiClassRefType(LType);
 
      if (LMeta.MetaclassType.InheritsFrom(TComponent)) then 
      begin 
        WriteLn('The metaclass type name is ', LType.Name); 
        WriteLn('The hierarchy starts at ', LMeta.InstanceType.Name); 
      end; 
    end; 
end.

Sehen Sie sich zum besseren Verständnis der von dem obigen Beispiel ausgegebenen Informationen diese Typdefinition an:

type
  TButtonClass = class of TButton;

Für diesen Typ gibt die Eigenschaft MetaclassType die Metaklasse selbst zurück, und die Eigenschaft InstanceType gibt die Typinformationen der Klasse TButton zurück. TButton steht in diesem Fall am Anfang der Metaklassenhierarchie.

Methoden und prozedurale Typen

Methodentypen werden von TRttiMethodType-Klasseninstanzen beschrieben und prozedurale Typen von TRttiProcedureType-Instanzen. Weder TRttiMethodType noch TRttiMethodType stellt zusätzliche Informationen bereit und sollte nur zum Feststellen der Typen verwendet werden:

{ Alle in der Anwendung deklarierten Ereignistypen suchen und ausgeben } 
for LType in LContext.GetTypes() do 
  if (LType is TRttiMethodType) and EndsStr('Event', LType.Name) then 
    WriteLn(LType.Name);

Zeiger

In Delphi werden auch für Zeigertypen RTTI-Informationen ausgegeben. Sie werden durch TRttiPointerType-Klasseninstanzen repräsentiert. TRttiPointerType stellt eine einzige Eigenschaft, ReferredType, bereit, die die Typinformationen für den referenzierten Typ enthält.

Für den folgenden Typ:

type
  TStrPtr = ^String;

stellt die Eigenschaft ReferredType beispielsweise die Typinformationen für den String-Typ bereit, auf den der Zeigertyp zeigt. Der folgende Code zeigt, wie diese Informationen abgerufen werden:

var
  LContext: TRttiContext;
  LType: TRttiPointerType;

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

  LType := LContext.GetType(TypeInfo(TStrPtr)) as TRttiPointerType;
  Writeln(LType.ReferredType.Name);
end.

Beachten Sie bitte, dass für untypisierte Zeigertypen (wie Pointer) ReferredType nil ist, weil nicht auf einen speziellen Typ gezeigt wird.

Siehe auch