メタデータ トークン

メタデータとは、ランタイム型 (クラス、値型、インターフェイス)、グローバル関数、グローバル変数などの抽象化に関する宣言情報です。 メタデータはテーブルに格納されています。抽象化の各カテゴリが 1 つのテーブルになっていて、抽象化の各宣言がテーブル内の 1 つの行になっています。 抽象化のメタデータが入っているレコードの位置を指定するために、トークン (mdToken 型のオブジェクト) を使用します。 メタデータ エンジンはこのトークンを使用して、特定のメタデータ スコープにある特定のメタデータ テーブルに索引を生成します。

メタデータ トークンの構造

メタデータ トークンは、4 バイトで構成される値です。 最上位バイト (MSB) ではトークン タイプを判別できます。言い換えれば、抽象化とそれに関連したメタデータ テーブルを識別できます。 例えば、MSB の値が 1 であれば、このトークンは型参照に相当する mdTypeRef トークンであり、そのメタデータは TypeRef メタデータ テーブルに格納されています。また、MSB の値が 4 の場合は、mdFieldDef トークンになります。 トークン型を指定するには、CorTokenType 列挙型を使用します。

下位 3 バイトはレコード識別子 (RID) と呼ばれており、トークンの MSB で参照しているメタデータ テーブル内の行の索引が入っています。 例えば、0x02000007 という値のメタデータ トークンは、現在のスコープにある TypeDef テーブルの行 7 を参照します。 また、0x0400001A というトークンは、現在のスコープにある FieldDef テーブルの行 26 (10 進数) を参照します。 メタデータ テーブルの行 0 (ゼロ) にはデータが格納されることはないので、RID がゼロのメタデータ トークンは Nil トークンと呼ばれます。 メタデータ API は、そのような Nil トークンのホストを定義します。各トークン型 (mdTypeRefNil など) について 1 つのホストが、値 0x01000000 で定義されます。

注意

前述の RID の説明は概念的なものです。実際には、メタデータの物理的なレイアウトははるかに複雑です。また、文字列トークン (mdString) の場合はいくらか異なっています。下位 3 バイトはレコード識別子ではなく、メタデータ文字列プール内にある文字列の開始位置へのオフセットになります。

メタデータ トークンの使用

メタデータ API に含まれている各 DefineXXX メソッドは、トークンを返します。そのトークンを GetXXX メソッドに渡すと、そのトークンに関連付けられた属性を取得できます。

メタデータ トークンはスコープ内で定義されます。 例えば、N という値のメタデータ トークンを使用すれば、特定のスコープ内で型定義に関する詳細情報が入っているレコードを完全に識別できます。 ただし、別のスコープでは、その同じ N という値のメタデータ トークンがまったく別のレコードを指す可能性があります。

メタデータ トークンは、変更不可のメタデータ オブジェクト識別子ではありません。 2 つのスコープをマージすると、インポートされたスコープのトークンが生成されたスコープのトークンに再マップされます。 メタデータ スコープを保存した場合も、各種の形式の最適化によってトークンの再マップが発生することがあります。

トークン型

メタデータのトークン型、各トークン型表す抽象化、その抽象化のメタデータが入っているメタデータ テーブルの名前を以下の表にまとめます。 すべてのトークン型は、基本のトークン型である mdToken のバリエーションです。 mdToken は、CorHdr.h ヘッダー ファイルで以下のように定義されています。

typedef ULONG32 mdToken;

トークン型

メタデータ テーブル

抽象化

mdModule

Module

モジュール: コンパイル単位、実行可能ファイル、その他の開発単位、配置単位、ランタイム単位。 モジュールの各属性 (名前、GUID、カスタム属性など) を全体としてまとめて宣言できます (必須ではありません)。

mdModuleRef

ModuleRef

モジュール参照: モジュールに対するコンパイル単位参照。型とメンバーのインポート元ソースを記録します。

mdTypeDef

TypeDef

型宣言: ランタイム参照型 (クラスまたはインターフェイス) または値型の宣言。

mdTypeRef

TypeRef

型参照: ランタイム参照型または値型への参照。 ある意味で、モジュール内の型参照のコレクションは、コンパイル時のインポートの依存関係のコレクションであるともいえます。

mdMethodDef

MethodDef

メソッド定義: クラスまたはインターフェイスのメンバーとしての、またはグローバル モジュール レベル メソッドとしてのメソッドの定義。

mdParamDef

ParamDef

パラメーター宣言: パラメーターの追加のメタデータを格納するオプションのデータ構造の定義。 メソッドの各パラメーターのデータ構造を生成する必要はありません。 ただし、マーシャリング情報や型のマッピング情報など、パラメーターに対して永続的な追加のメタデータがある場合は、オプションのパラメーター データ構造を作成できます。

mdFieldDef

FieldDef

フィールド宣言: クラスまたはインターフェイスのデータ メンバーとしての変数の宣言、またはグローバル モジュール レベル変数の宣言。

mdProperty

プロパティ

プロパティ宣言: クラスまたはインターフェイスのメンバーとしてのプロパティの宣言。

mdEvent

Event

イベント宣言: クラスまたはインターフェイスのメンバーとしての名前付きイベントの宣言。

mdMemberRef

MemberRef

メンバー参照: メソッドまたはフィールドへの参照。 現在のモジュールに含まれている実装からのあらゆるメソッド呼び出しまたはフィールド アクセスごとに、メンバー参照がメタデータ内で生成されます。トークンは、MSIL (Microsoft Intermediate Language) ストリーム内で永続します。 プロパティ参照またはイベント参照のランタイム サポートはありません。

mdIfaceImpl

IfaceImpl

インターフェイス実装: 特定のインターフェイスの特定のクラスの実装。 このメタデータ抽象化によって、クラス固有でもインターフェイス固有でもない、そのクラスのそのインターフェイス固有の情報を格納できるようになります。

mdMethodImpl

MethodImpl

メソッド実装: インターフェイス継承を使用して継承したメソッドの特定のクラスの実装。 このメタデータ抽象化によって、コントラクト固有ではなく実装固有の情報を永続化できるようになります。 実装クラスによってメソッド宣言の情報を変更することはできません。

mdCustomAttribute

CustomAttribute

カスタム属性: mdToken で参照できるメタデータ オブジェクトに関連付けられた任意のデータ構造。 (例外として、カスタム属性そのものにカスタム属性を設定することはできません。)

mdPermission

アクセス許可

アクセス許可セット: mdTypeDefmdMethodDefmdAssembly に関連付けられた宣言セキュリティ アクセス許可セット。 詳細については、「宣言セキュリティのサポートの追加」を参照してください。

mdTypeSpec

TypeSpec

型コンストラクター: 型を使用する MSIL 命令への入力として使用できる型 (ボックス化された値型など) のトークンを取得するメソッド。

mdSignature

Signature

スタンドアロン シグネチャ: 移植可能な実行可能 (PE) ファイル内のローカル変数シグネチャ、または MSIL 命令に渡されるメソッド シグネチャ。

mdString

String

ユーザー文字列: MSIL 命令に渡される文字列。

注意

前述のリストには、2 つのトークン型が含まれていません。1 つはフィールド参照用で、もう 1 つはメソッド参照用です。フィールド参照とメソッド参照は同じテーブルを共有しており、トークン型 mdMemberRef を使用して参照できます。

拡張性と抽象化

ランタイム メタデータは拡張できます。これは次のような状況で重要です。

  • 共通言語仕様 (CLS: Common Language Specification) によって定義された制約または高度な抽象化を表す場合。 CLS は、各種言語と各種ツールのサポートを統一化して言語統合を促進するための共通規則の仕様です。 CLS では、共通型システム モデルの一部を制約し、共通型システムの上層に配置される上位の抽象化を導入できます。 ランタイムが抽象化を明示的に認識またはサポートしていない場合でも、メタデータはツールで使用されるこの種の開発時の抽象化を取り込める必要があります。

  • 共通型システムの一部ではなく CLS 抽象化でもない言語固有の抽象化を表す場合。 これにより、コンパイル済みのモジュールがエクスポートした型、メソッド、データ メンバーを Visual C などの言語で使用するために、個別のヘッダー ファイルや IDL ファイルを必要としなくなります。

  • 言語固有のオーバーロードで使用するメンバー内シグネチャ型や型修飾子をエンコードする場合。

メタデータには以下のような拡張性があります。

  • どのメタデータ オブジェクトもカスタム属性に対応しています。また、メタデータ API には、カスタム属性の宣言、列挙、取得のための手段が用意されています。 カスタム属性は、型参照 (mdTypeDefmdTypeRef) によって識別できます。 カスタム属性の構造は、型で宣言するデータ メンバーを使用した自己記述型になっていて、値のエンコードはランタイム リフレクション サービスなどの任意のツールで表示できます。

  • 共通型システムを拡張するだけでなく、カスタム修飾子からメンバー シグネチャを生成することもできます。 ランタイムでは、メソッドのバインドだけでなくオーバーロードや非表示にもこれらの修飾子が利用されますが、言語固有のセマンティクスは適用されません。

参照

その他の技術情報

メタデータの概要