型情報のクエリ
RTTI の操作:インデックス への移動
はじめに
どんな RTTI 作業セッションも、型情報の取得からはじまります。Delphi で型情報が出力されるのは、型に対してだけです。グローバル ユニット ルーチン、定数、および変数に対しては出力されません。つまり、取得した TRttiContext を使用できるのは、宣言済みの型に関する情報を問い合わせるためだけです。
型に関する情報を取得する基本的な方法は、次の 3 つです。
- アプリケーションで宣言されているすべての型のリストを取得する。
- 型情報ハンドルか修飾名を指定して、特定の型の情報を検索する。
- これら 2 つの方法を用いて、個々の実行時パッケージ内の型を問い合わせる。
すべての型を列挙する
アプリケーションで宣言されているすべての型のリストを取得するには、TRttiContext.GetTypes メソッドを使用します。可視性がパブリックな型(ユニットの interface セクションで宣言されているもの)をすべて列挙し、TRttiType オブジェクトの配列を返します。各 TRttiType オブジェクトは、高レベルの API が、そのオブジェクトの持つ型に関する情報にアクセスできるようにします。次に例を示します。
var
LContext: TRttiContext;
LType: TRttiType;
begin
{ Obtain the RTTI context }
LContext := TRttiContext.Create;
{ Enumerate all types declared in the application }
for LType in LContext.GetTypes() do
Writeln(LType.Name);
LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
// Obtain the RTTI context
TRttiContext *context = new TRttiContext();
// Enumerate all types declared in the 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;
}
この例では、RTTI コンテキストを取得してから、それを使用してすべてのパブリックにアクセスできる型のリストを取得しています。その後、for ループで型の名前をコンソールに表示しています。
TRttiType インスタンスは、開発者がクリーンアップするべきではありません。前述のトピックで説明したように、TRttiContext には TRttiType インスタンスの存続期間を管理する責任があります。
特定の型の情報を取得する
実行時に情報を取得する必要のある型の名前が、コンパイル時にわかっている場合、TRttiContext には次の 2 つのメソッドがあります。
- TRttiContext.GetType。任意の System.TypInfo.PTypeInfo ハンドルの型情報を取得します。PTypeInfo ハンドルは、TypeInfo 演算子を使用することで、コンパイル時に取得されます。
- TRttiContext.FindType。修飾型名に基づいて、型情報を検索します。修飾型名は、ユニット名と型名という 2 つの要素から成ります。2 つの要素はピリオドで区切ります(たとえば、Classes.TStrings)。
これらのメソッドを使った例を次に示します。
var
LContext: TRttiContext;
LType: TRttiType;
begin
{ Obtain the RTTI context }
LContext := TRttiContext.Create;
{ Obtain the type information for Integer }
LType := LContext.GetType(TypeInfo(Integer));
Writeln(LType.Name);
{ Obtain the type information for a type in the Classes unit }
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[]) {
// Obtain the RTTI context
TRttiContext *context = new TRttiContext();
// Obtain the type information for Integer
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;
}
GetType および FindType は通常、型の名前や PTypeInfo ハンドルを間接的に取得する場合、実行時に役立ちます。
パッケージ情報
TRttiContext は、TRttiContext.GetPackages という特別なメソッドを公開します。このメソッドは、アプリケーションに現在読み込まれている実行時パッケージすべてを列挙できます(これには、パッケージの 1 つと認識される、メイン アプリケーション モジュールも含まれます)。GetPackages は、TRttiPackage インスタンスの配列を返します。これらのインスタンスは、次のように、パッケージ内で特別に宣言された型を取得できる関数をいくつか公開します。
var
LContext: TRttiContext;
LType: TRttiType;
LPackage: TRttiPackage;
begin
{ Obtain the RTTI context }
LContext := TRttiContext.Create;
{ Obtain the second package (rtl140) }
LPackage := LContext.GetPackages()[1];
{ Enumerate all types in the rtl140 package }
for LType in LPackage.GetTypes() do
Writeln(LType.Name);
LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
// Obtain the RTTI context
TRttiContext *context = new TRttiContext();
// Obtain the second package (rtl140)
DynamicArray<TRttiPackage*>packageArray = context->GetPackages();
TRttiPackage *package = packageArray[1];
// Enumerate all types in the rtl140 package
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;
}
この例では、2 番目に読み込まれたパッケージ(rtl140.bpl)に関する情報を取得してから、そのパッケージが公開するすべての型を取得しています。この例は実行時パッケージを使用してビルドする必要があることに注意してください。そうしなかった場合、型がアプリケーション内に直接ビルドされてしまいます。
TRttiContext と同様に、TRttiPackage も次のように修飾名で型を検索できます。
var
LContext: TRttiContext;
LType: TRttiType;
LPackage: TRttiPackage;
begin
{ Obtain the RTTI context }
LContext := TRttiContext.Create;
{ Obtain the second package (rtl140) }
LPackage := LContext.GetPackages()[1];
{ Get type information for the TStrings class }
LType := LPackage.FindType('Classes.TStrings');
Writeln(LType.Name);
LContext.Free;
end.
int _tmain(int argc, _TCHAR* argv[]) {
// Obtain the RTTI context
TRttiContext *context = new TRttiContext();
// Obtain the second package (rtl140)
DynamicArray<TRttiPackage*>packageArray = context->GetPackages();
TRttiPackage *package = packageArray[1];
// Get type information for the TStrings class
TRttiType *type = package->FindType("Classes.TStrings");
printf("%ls\n", type->Name.c_str());
delete context;
return 0;
}