メタデータ トークン
メタデータは、ランタイム型 (クラス、値型、およびインターフェイス)、グローバル関数、グローバル変数などの抽象化の宣言情報です。 メタデータはテーブルに格納されます。抽象化のカテゴリごとに 1 つのテーブルが作成され、抽象化の宣言ごとにテーブルの 1 行が作成されます。 トークン (mdToken 型のオブジェクト) は、抽象化用のメタデータを含むレコードを検索するために使用されます。 メタデータ エンジンはトークンを使用して、指定されたメタデータ スコープ内の特定のメタデータ テーブルにインデックスを設定します。
メタデータ トークンの構造
メタデータ トークンは、4 バイトで構成される値です。 最上位バイト (MSB: Most Significant Byte) はトークンの種類を指定し、抽象化とそれに関連するメタデータ テーブルを識別します。 たとえば、MSB の値 1 は、トークンが mdTypeRef トークンであることを意味します。このトークンは型参照を表し、そのメタデータは TypeRef メタデータ テーブルに格納されます。MSB の値 4 は、mdFieldDef トークンに対応します。 CorTokenType 列挙型を使用して、トークンの種類を指定します。
下位 3 バイトはレコード ID (RID) と呼ばれ、トークンの MSB が参照するメタデータ テーブルにある行のインデックスが格納されます。 たとえば、値 0x02000007 を持つメタデータ トークンは、現在のスコープの TypeDef テーブル内にある行 7 を参照します。 同様に、トークン 0x0400001A は、現在のスコープの FieldDef テーブル内にある行 26 (10 進数) を参照します。 メタデータ テーブルの行ゼロにデータが格納されることはないため、RID がゼロのメタデータ トークンは nil トークンと呼ばれます。 メタデータ API はこのような nil トークンのホストを定義します。トークンの種類 (mdTypeRefNil など) ごとに 1 つのホストが、値 0x01000000 を使用して定義されます。
メモ |
---|
前述の RID の説明は概念的なものです。実際には、メタデータの物理レイアウトはかなり複雑です。また、文字列トークン (mdString) は若干異なります。下位 3 バイトはレコード ID ではなく、メタデータ文字列プール内にある文字列の開始位置へのオフセットを表します。 |
メタデータ トークンの使用
メタデータ API 内の各 DefineXXX メソッドは、トークンを返します。このトークンを GetXXX メソッドに渡して、関連付けられた属性を取得することができます。
メタデータ トークンはスコープ内で定義されます。 たとえば、値 N を持つメタデータ トークンは、あるスコープ内で型定義に関する詳細を含むレコードを完全に識別します。 しかし、別のスコープでは、同じ値 N を持つメタデータ トークンが、まったく異なるレコードを指定する場合もあります。
メタデータ トークンは、変更できないメタデータ オブジェクト識別子ではありません。 2 つのスコープがマージされると、インポートされたスコープのトークンは、生成されたスコープ内のトークンに再マップされます。 メタデータ スコープを保存すると、さまざまな形式の最適化により、トークンが再マップされる可能性があります。
トークンの種類
次の表に、メタデータ トークンの種類、各トークンの種類が表す抽象化、および抽象化のメタデータを含むメタデータ テーブルの名前を示します。 トークンの種類はすべて、基本的なトークンの種類である mdToken のバリエーションです。
トークンの種類 |
メタデータ テーブル |
抽象化クラス |
---|---|---|
mdModule |
[モジュール] |
モジュール : コンパイル単位、実行可能ファイル、その他の開発単位、配置単位、ランタイム単位。 名前、GUID、カスタム属性などの属性を、モジュール全体に対して宣言できます (必須ではありません)。 |
mdModuleRef |
ModuleRef |
モジュール参照 : コンパイル時のモジュールへの参照。型およびメンバーのインポート元ソースを記録します。 |
mdTypeDef |
typedef |
型宣言 : ランタイム参照型 (クラスまたはインターフェイス) または値型の宣言。 |
mdTypeRef |
TypeRef |
型参照 : ランタイム参照型または値型への参照。 ある意味では、モジュール内にある型参照のコレクションは、コンパイル時のインポート依存関係のコレクションです。 |
mdMethodDef |
MethodDef |
メソッド定義 : クラスまたはインターフェイスのメンバー、あるいはグローバル モジュール レベル メソッドとしてのメソッドの定義。 |
mdParamDef |
ParamDef |
パラメーター宣言 : パラメーターに関する追加のメタデータを格納するオプションのデータ構造の定義。 メソッド内のパラメーターごとにデータ構造を生成する必要はありません。 ただし、マーシャリング情報や型のマッピング情報など、特定のパラメーターに対して持続的な追加のメタデータがある場合、オプションのパラメーター データ構造を作成できます。 |
mdFieldDef |
FieldDef |
フィールド宣言 : クラスまたはインターフェイスのデータ メンバーとしての変数の宣言、あるいはグローバルなモジュール レベル変数の宣言。 |
mdProperty |
プロパティ |
プロパティ宣言 : クラスまたはインターフェイスのメンバーとしてのプロパティの宣言。 |
mdEvent |
イベント |
イベント宣言 : クラスまたはインターフェイスのメンバーとしての名前付きイベントの宣言。 |
mdMemberRef |
MemberRef |
メンバー参照 : メソッドまたはフィールドへの参照。 メンバー参照は、現在のモジュール内の任意の実装によって行われるメソッド呼び出しまたはフィールド アクセスごとにメタデータで生成され、トークンは Microsoft Intermediate Language (MSIL) ストリームに保持されます。 プロパティ参照またはイベント参照のランタイム サポートはありません。 |
mdIfaceImpl |
IfaceImpl |
インターフェイス実装 : 特定のクラスにおける特定のインターフェイスの実装。 このメタデータ抽象化により、クラス固有とインターフェイス固有のどちらでもなく、そのクラスのそのインターフェイス固有である情報を格納できます。 |
mdMethodImpl |
MethodImpl |
メソッド実装 : インターフェイス継承を使用して継承されるメソッドの特定のクラスにおける実装。 このメタデータ抽象化により、コントラクト固有ではなく実装固有の情報を保持できます。 メソッド宣言情報を、そのメソッドを実装するクラスが変更することはできません。 |
mdCustomAttribute |
CustomAttribute |
カスタム属性 : mdToken を使用して参照できる任意のメタデータ オブジェクトに対して関連付けられた任意のデータ構造。 例外として、カスタム属性自体はカスタム属性を持つことができません。 |
mdPermission |
Permission |
アクセス許可セット : mdTypeDef、mdMethodDef、および mdAssembly に関連付けられた宣言セキュリティ アクセス許可セット。 詳細については、「宣言セキュリティのサポートの追加」を参照してください。 |
mdTypeSpec |
TypeSpec |
型コンストラクター : 型を使用する MSIL 命令への入力として使用できる型 (ボックス化された値の型など) のトークンを取得するメソッド。 |
mdSignature |
Signature |
スタンドアロン シグネチャ : 移植可能な実行可能 (PE: Portable Executable) ファイル内のローカル変数シグネチャ、または MSIL 命令に渡されるメソッド シグネチャ。 |
mdString |
String |
ユーザー文字列 : MSIL 命令に渡される文字列。 |
メモ |
---|
前述の一覧には、2 種類の別個のトークンが含まれていません。1 つはフィールド参照用のトークン、もう 1 つはメソッド参照用です。フィールド参照とメソッド参照は同じテーブルを共有し、種類が mdMemberRef のトークンを使用して参照できます。 |
機能拡張と抽象化
ランタイム メタデータは拡張できます。これは次のような状況で重要です。
共通言語仕様 (CLS: Common Language Specification) によって定義された制約または上位の抽象化を表す場合。 CLS とは、言語とツールを一貫した方法でサポートすることに合意した規則から成る仕様で、言語を効果的に統合するためのものです。 CLS は共通型システム モデルの一部を制約し、共通型システムの上層に配置される上位の抽象化を導入できます。 ランタイムが抽象化を明示的に認識またはサポートしていない場合でも、メタデータはツールで使用されるこの種の開発時の抽象化に対処できる必要があります。
共通型システムの一部ではなく、CLS 抽象化でもない言語固有の抽象化を表す場合。 これにより、コンパイル済みのモジュールがエクスポートした型、メソッド、およびデータ メンバーを Visual C のような言語で使用するために、個別のヘッダー ファイルまたは IDL ファイルを使用する必要がなくなります。
言語固有のオーバーロードで使用されるメンバー内シグネチャ型および型修飾子をエンコードする場合。
メタデータは次のように機能拡張されます。
すべてのメタデータ オブジェクトがカスタム属性をサポートできます。また、メタデータ API はカスタム属性を宣言、列挙、および取得する方法を提供します。 カスタム属性は、型参照 (mdTypeDef および mdTypeRef) で識別できます。 カスタム属性の構造は、型で宣言されたデータ メンバーを使用する自己記述型で、値エンコーディングは、ランタイム リフレクション サービスを含む任意のツールで参照できます。
共通型システムを拡張するだけでなく、カスタム修飾子をメンバー シグネチャに出力することもできます。 ランタイムでは、メソッドのバインドだけでなくオーバーロードおよび非表示にもこれらの修飾子が適用されますが、言語固有のセマンティクスは適用されません。