Informations des types simples

De RAD Studio
Aller à : navigation, rechercher

Remonter à Utilisation des informations RTTI - Index

Introduction

Dans Delphi, il existe deux catégories de types de base : simples et structurés. En termes d'informations de types, les types simples transportent généralement beaucoup moins d'informations que les types structurés.

Pour vérifier si le TRttiType obtenu reflète un type donné, utilisez la propriété TRttiType.TypeKind. Sa valeur spécifie le genre de type réel. L'autre méthode consiste à utiliser l'opérateur is pour détecter le type classe réel pour une instance de TRttiType :

    { Afficher seulement les types chaîne }
    for LType in LContext.GetTypes() do
        if LType is TRttiStringType then
            Writeln(LType.ToString);
    // Afficher seulement les types chaîne
    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());
        }
    }

L'exemple précédent affiche seulement les types chaîne déclarés dans l'application et ses packages.

Types ordinaux

Les types ordinaux sont décrits par les instances de la classe TRttiOrdinalType. TRttiOrdinalType expose les propriétés utilisées pour accéder aux informations spécifiques aux types ordinaux tels que MinValue, MaxValue et OrdType.

L'exemple suivant énumère tous les types ordinaux définis dans l'application ou ses packages, et imprime leurs propriétés sur la console :

    for LType in LContext.GetTypes() do
        if LType is TRttiOrdinalType then
        begin
            Writeln('Nom du type :', LType.Name);
            Writeln('Valeur minimale permise :', TRttiOrdinalType(LType).MinValue);
            Writeln('Valeur maximale permise :', TRttiOrdinalType(LType).MaxValue);
            Writeln;
        end;
    // Enumérer tous les types déclarés dans l'application
    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 valeur minimale : %ld\n", ordinalType->MinValue);
            printf("\t valeur maximale : %ld\n", ordinalType->MaxValue);
        }
    }

Notez que les types énumération sont aussi considérés comme des ordinaux. Ainsi, l'exemple précédent imprimera aussi les informations qu'ils contiennent.

Types entier 64 bits

Les entiers 64 bits ne partagent pas le même type de base que les types ordinaux. Pour cette raison, les entiers 64 bits sont décrits par la classe TRttiInt64Type. TRttiInt64Type expose les propriétés MinValue et MaxValue, de façon identique à TRttiOrdinalType.

L'exemple suivant énumère tous les entiers 64 bits déclarés dans l'application ou ses packages :

    for LType in LContext.GetTypes() do
        if LType is TRttiInt64Type then
        begin
            Writeln('Nom du type :', LType.Name);
            Writeln('Valeur minimale permise :', TRttiInt64Type(LType).MinValue);
            Writeln('Valeur maximale permise :', 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("nom du type : %ls\n", int64Type->ToString().c_str());
            printf("\t valeur minimale permise : %Ld\n", int64Type->MinValue);
            printf("\t valeur maximale permise : %Ld\n", int64Type->MaxValue);
        }
    }

Types à virgule flottante

Les types à virgule flottante sont décrits par les instances de la classe TRttiFloatType. TRttiFloatType expose une seule propriété, appelée FloatType, qui permet l'identification du sous-type à virgule flottante.

L'exemple suivant imprime tous les types à virgule flottante déclarés dont le sous-type est Double :

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

Les résultats imprimés incluent le type Double lui-même, le type Real, qui est un type double et les types date-heure déclarés dans l'unité System.

Types ensemble

Les types ensemble sont décrits par les instances de la classe TRttiSetType. La seule propriété exposée par TRttiSetType est ElementType. Elle fournit les informations de type pour les éléments qui constituent l'ensemble. Par exemple, soit un ensemble défini par :

type
  TByteSet = set of Byte;

le code suivant imprime le nom du type de l'ensemble des éléments (qui est Byte) :

var
  LContext: TRttiContext;
  LType: TRttiSetType;

begin
  { Obtenir le contexte RTTI }
  LContext := TRttiContext.Create;

  { Obtenir le TRttiSetType pour notre type }
  LType := LContext.GetType(TypeInfo(TByteSet)) as TRttiSetType;

  { Imprimer le nom du type des éléments de l'ensemble }
  Writeln('Les éléments de l'ensemble sont du ', LType.ElementType.Name, ' type.');
end.

Types énumération

Les types énumération sont décrits par les instances de la classe TRttiEnumerationType. TRttiEnumerationType est dérivé de TRttiOrdinalType et y ajoute une nouvelle propriété, appelée UnderlyingType. UnderlyingType fournit les informations de type pour le type énumération réel qui est utilisé dans ce type énumération.

Considérons deux types énumération, un nouveau et l'autre étant un alias de l'énumération TSeekOrigin standard :

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

Le code suivant imprime le nom du type sous-jacent pour les deux types :

  { Obtenir les informations de type pour les deux types }
  LType1 := LContext.GetType(TypeInfo(TNewEnum)) as TRttiEnumerationType;
  LType2 := LContext.GetType(TypeInfo(TOtherEnum)) as TRttiEnumerationType;

  { Imprimer les noms de type pour les types sous-jacents }
  Writeln('Type sous-jacent pour TNewEnum est ', LType1.UnderlyingType.Name);
  Writeln('Type sous-jacent pour TOtherEnum est ', LType2.UnderlyingType.Name);

Notez que, pour les types énumération récemment déclarés (par exemple, TNewEnum), la propriété UnderlyingType renvoie les informations de type pour le type énumération lui-même. Pour les types à fort alias (tels que TOtherEnum), UnderlyingType renvoie les informations de ce type.

Chaînes

Les types chaîne sont décrits par les instances de la classe TRttiStringType. TRttiStringType expose une seule propriété, appelée StringKind, qui permet l'identification du type chaîne réel. Voici les valeurs possibles du type chaîne :

  • Chaîne courte
  • Chaîne Ansi
  • Chaîne étendue
  • Chaîne Unicode

L'exemple suivant imprime tous les types chaîne ANSI déclarés dans l'application ou ses packages :

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

Pour les types AnsiString, l'unité Rtti définit une classe TRttiAnsiStringType spéciale. TRttiAnsiStringType est dérivé de TRttiStringType et il ajoute une nouvelle propriété CodePage, qui peut être utilisée pour obtenir la page de code du AnsiString.

L'exemple suivant imprime la page de code du type RawByteString :

{ Obtenir les informations de type pour RawByteString (qui est un AnsiString) }
LType := LContext.GetType(TypeInfo(RawByteString)) as TRttiAnsiStringType;
Writeln('La page de code de la chaîne est ', LType.CodePage);

Références de classes (métaclasses)

Les types référence de classe sont décrits par les instances de la classe TRttiClassRefType. TRttiClassRefType permet d'obtenir le type classe utilisé pour la base de la hiérarchie indiquée par la métaclasse (à l'aide de la propriété InstanceType). TRttiClassRefType fournit aussi un accès direct à la métaclasse elle-même, par le biais de MetaclassType.

L'exemple suivant imprime tous les types métaclasse déclarés dans l'application ou ses packages ; ils représentent les types dérivés de TComponent :

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

begin
  { Obtenir le contexte RTTI }
  LContext := TRttiContext.Create;

  { Obtenir tous les types qui sont des références de classe et dont la classe hérite de TComponent }
  for LType in LContext.GetTypes() do
    if (LType is TRttiClassRefType) then
    begin
      { Transtyper la classe de type Rtti }
      LMeta := TRttiClassRefType(LType);

      if (LMeta.MetaclassType.InheritsFrom(TComponent)) then
      begin
        Writeln('Le nom de type de la métaclasse est ', LType.Name);
        Writeln('La hiérarchie commence à ', LMeta.InstanceType.Name);
      end;
    end;
end.

Afin de mieux comprendre les informations listées par l'exemple précédent, considérons cette définition de type :

type
  TButtonClass = class of TButton;

Pour ce type, la propriété MetaclassType renvoie la métaclasse elle-même, tandis que la propriété InstanceType renvoie les informations de type de la classe TButton. Dans ce cas, TButton démarre la hiérarchie de la métaclasse.

Types procéduraux et types méthode

Les types méthode sont décrits par les instances de la classe TRttiMethodType, tandis que les types procéduraux sont décrits par les instances de TRttiProcedureType. Ni TRttiMethodType, ni TRttiProcedureType ne fournit des informations supplémentaires, et ils doivent seulement être utilisés pour détecter les types :

{ Chercher et imprimer tous les types d'événements déclarés dans l'application }
for LType in LContext.GetTypes() do
  if (LType is TRttiMethodType) and EndsStr('Event', LType.Name) then
    Writeln(LType.Name);

Pointeurs

Dans Delphi, des informations RTTI sont aussi émises pour les types pointeur. Ils sont représentés par les instances de la classe TRttiPointerType. TRttiPointerType expose une seule propriété, ReferredType, qui fournit des informations de type pour le type pointé.

Par exemple, soit le type suivant :

type
  TStrPtr = ^String;

la propriété ReferredType fournit des informations de type pour le type String qui est pointé par le type pointeur. Le code suivant illustre comment obtenir ces informations :

var
  LContext: TRttiContext;
  LType: TRttiPointerType;

begin
  { Obtenir le contexte RTTI }
  LContext := TRttiContext.Create;

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

Notez que pour les types pointeur non typés (tels que Pointer), ReferredType vaut nil car il ne pointe pas sur un type spécifique.

Voir aussi