Interrogation des informations de type

De RAD Studio
Aller à : navigation, rechercher

Remonter à Utilisation des informations RTTI - Index


Introduction

Le point de départ de toute session de travail RTTI est l'obtention des informations de type. Dans Delphi, les informations de type sont émises seulement pour les types et non pour les variables, les constantes ou les routines d'unités globales. Cela signifie que le contexte TRttiContext obtenu peut seulement être utilisé pour interroger les informations à propos des types déclarés.

Il existe trois méthodes de base pour obtenir des informations à propos d'un type :

  • Obtenir une liste de tous les types déclarés dans l'application.
  • Chercher les informations d'un type spécifique, à partir de son handle d'information de type ou nom qualifié.
  • Utiliser les deux premières méthodes pour interroger les types de packages d'exécution individuels.

Enumération de tous les types

Pour obtenir la liste de tous les types déclarés dans une application, utilisez la méthode TRttiContext.GetTypes. Elle énumère tous les types publiquement visibles (ceux déclarés dans la section interface des unités) et renvoie un tableau d'objets TRttiType. Chaque objet TRttiType fournit une API de niveau élevé pour accéder aux informations du type qu'il décrit :

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

    { Enumérer tous les types déclarés dans l'application }
    for LType in LContext.GetTypes() do
        Writeln(LType.Name);

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Obtenir le contexte RTTI
    TRttiContext *context = new TRttiContext();

    // 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];
        printf("%ls\n", type->Name.c_str());
    }

    delete context;
    return 0;
}

L'exemple précédent obtient le contexte RTTI, puis l'utilise pour obtenir la liste de tous les types publiquement disponibles. La boucle for imprime ensuite les noms des types vers la console.

Les instances de TRttiType ne doivent pas être nettoyées par le développeur. Comme décrit dans la rubrique précédente, le contexte TRttiContext est responsable de la gestion de leur cycle de vie.

Obtention d'informations pour un type spécifique

Si le nom du type pour lequel les informations doivent être obtenues à l'exécution est connu à la compilation, TRttiContext inclut deux autres méthodes :

  • TRttiContext.GetType, qui obtient les informations de type pour un handle System.TypInfo.PTypeInfo donné. Le handle PTypeInfo est obtenu à la compilation, en utilisant l'opérateur TypeInfo.
  • TRttiContext.FindType, qui recherche les informations de type basées sur le nom de type qualifié. Le nom de type qualifié est constitué de deux composants : le nom d'unité, séparé par le caractère point du nom de type (par exemple, Classes.TStrings).

L'exemple suivant illustre l'utilisation des méthodes mentionnées :

var
    LContext: TRttiContext;
    LType: TRttiType;

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

    { Obtenir les informations de type pour Integer }
    LType := LContext.GetType(TypeInfo(Integer));
    Writeln(LType.Name);

    { Obtenir les informations de type pour un type de l'unité Classes }
    LType := LContext.FindType('Classes.TStrings');
    if not LType.IsInstance then
        Writeln('TStrings est supposé être une classe !');

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Obtenir le contexte RTTI
    TRttiContext *context = new TRttiContext();

    // Obtenir les informations de type pour Integer
    TRttiType *type = context->GetType(__delphirtti(Integer));
    printf("%ls\n", type->Name.c_str());

    type = context->FindType("Classes.TStrings");
    if ((type->IsInstance) == false) {
        puts("TStrings est supposé être une classe !");
    }

    delete context;
    return 0;
}

Normalement, GetType et FindType sont utiles à l'exécution, quand le nom du type ou le handle PTypeInfo est obtenu indirectement.

Informations de package

TRttiContext expose une méthode spéciale, appelée TRttiContext.GetPackages, qui vous permet d'énumérer tous les packages d'exécution actuellement chargés dans l'application (y compris le module principal de l'application, aussi considéré comme un package). GetPackages renvoie un tableau d'instances de TRttiPackage. Les instances exposent un certain nombre de fonctions qui permettent d'obtenir les types spécifiquement déclarés dans le package :

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

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

    { Obtenir le second package (rtl140) }
    LPackage := LContext.GetPackages()[1];

    { Enumérer tous les types du package rtl140 }
    for LType in LPackage.GetTypes() do
        Writeln(LType.Name);

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Obtenir le contexte RTTI
    TRttiContext *context = new TRttiContext();

    // Obtenir le second package (rtl140)
    DynamicArray<TRttiPackage*>packageArray = context->GetPackages();
    TRttiPackage *package = packageArray[1];

    // Enumérer tous les types du package rtl140
    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;
}

L'exemple précédent obtient des informations sur le package chargé en second (dans notre cas, rtl140.bpl), puis récupère tous les types exposés par ce package. Notez que l'exemple doit être construit en utilisant les packages d'exécution ; sinon, les types sont construits directement dans l'application.

De même que TRttiContext, TRttiPackage vous permet de trouver le type par son nom qualifié :

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

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

    { Obtenir le second package (rtl140) }
    LPackage := LContext.GetPackages()[1];

    { Obtenir les informations de type pour la classe TStrings }
    LType := LPackage.FindType('Classes.TStrings');
    Writeln(LType.Name);

    LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
    // Obtenir le contexte RTTI
    TRttiContext *context = new TRttiContext();

    // Obtenir le second package (rtl140)
    DynamicArray<TRttiPackage*>packageArray = context->GetPackages();
    TRttiPackage *package = packageArray[1];

    // Obtenir les informations de type pour la classe TStrings
    TRttiType *type = package->FindType("Classes.TStrings");
    printf("%ls\n", type->Name.c_str());

    delete context;
    return 0;
}

Voir aussi