Abfragen von Typinformationen
Nach oben zu Mit RTTI arbeiten
Inhaltsverzeichnis
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;
}