メタデータと自己言及的なコンポーネントMetadata and Self-Describing Components

以前は、ある 1 つの言語で記述されたソフトウェア コンポーネント (.exe または .dll) で、別の言語で記述されたコンポーネントを使用するのは簡単ではありませんでした。In the past, a software component (.exe or .dll) that was written in one language could not easily use a software component that was written in another language. COM により、この問題が解決するための手段が提供されるようになりました。COM provided a step towards solving this problem. .NET Framework では、コンパイラからすべてのモジュールやアセンブリに追加の宣言情報を挿入できるようになり、コンポーネントの相互運用性が大幅に強化されています。The .NET Framework makes component interoperation even easier by allowing compilers to emit additional declarative information into all modules and assemblies. メタデータと呼ばれるこの情報により、コンポーネント間のシームレスな相互作用がサポートされます。This information, called metadata, helps components to interact seamlessly.

メタデータはプログラムを説明するバイナリ情報であり、共通言語ランタイムのポータブル実行可能 (PE) ファイルまたはメモリのいずれかに格納されます。Metadata is binary information describing your program that is stored either in a common language runtime portable executable (PE) file or in memory. コードを PE ファイルとしてコンパイルすると、PE ファイルの特定の部分にメタデータが挿入され、コードは Microsoft Intermediate Language (MSIL) に変換されて PE ファイル内の別の部分に挿入されます。When you compile your code into a PE file, metadata is inserted into one portion of the file, and your code is converted to Microsoft intermediate language (MSIL) and inserted into another portion of the file. モジュール内またはアセンブリ内で定義され、参照されているすべての型およびメンバーは、メタデータ内部に記述されます。Every type and member that is defined and referenced in a module or assembly is described within metadata. コードを実行すると、ランタイムはメタデータをメモリに読み込み、コードのクラス、メンバー、継承などの情報を検索するためにメタデータを参照します。When code is executed, the runtime loads metadata into memory and references it to discover information about your code's classes, members, inheritance, and so on.

メタデータには、コードに定義されているすべての型およびメンバーが言語に中立的な形で記述されています。Metadata describes every type and member defined in your code in a language-neutral manner. メタデータには、次の情報が格納されいてます。Metadata stores the following information:

  • アセンブリに関する記述Description of the assembly.

    • ID (名前、バージョン、カルチャ、公開キー)Identity (name, version, culture, public key).

    • エクスポートされる型The types that are exported.

    • そのアセンブリが依存している他のアセンブリOther assemblies that this assembly depends on.

    • 実行のために必要なセキュリティ アクセス許可Security permissions needed to run.

  • 型に関する説明Description of types.

    • 名前、参照可能範囲、基底クラス、および実装されているインターフェイスName, visibility, base class, and interfaces implemented.

    • メンバー (メソッド、フィールド、プロパティ、イベント、入れ子になった型)Members (methods, fields, properties, events, nested types).

  • 属性。Attributes.

    • 型やメンバーを修飾する追加の記述要素Additional descriptive elements that modify types and members.

メタデータの利点Benefits of Metadata

メタデータは、プログラミング モデルを簡素化するうえで重要な役割を果たします。これにより、インターフェイス定義言語 (IDL: Interface Definition Language) ファイル、ヘッダー ファイル、およびその他のコンポーネント参照の外部メソッドは一切不要になります。Metadata is the key to a simpler programming model, and eliminates the need for Interface Definition Language (IDL) files, header files, or any external method of component reference. メタデータを使用すると、.NET Framework の各言語は、開発者やユーザーからは見えない、言語に依存しない形式で自動的に記述されるようになります。Metadata enables .NET Framework languages to describe themselves automatically in a language-neutral manner, unseen by both the developer and the user. また、属性を使用することにより、メタデータを拡張することもできます。Additionally, metadata is extensible through the use of attributes. メタデータの主な利点は、次のとおりです。Metadata provides the following major benefits:

  • 自己言及的なファイルSelf-describing files.

    共通言語ランタイム モジュールおよびアセンブリは、自己言及的なファイルです。Common language runtime modules and assemblies are self-describing. モジュールのメタデータには、他のモジュールと相互作用するのに必要なすべての情報が含まれています。A module's metadata contains everything needed to interact with another module. メタデータは自動的に COM の IDL の機能を提供するため、ユーザーは 1 つのファイルを定義と実装の両方に使用できます。Metadata automatically provides the functionality of IDL in COM, so you can use one file for both definition and implementation. また、ランタイム モジュールやアセンブリをオペレーティング システムに登録する必要もありません。Runtime modules and assemblies do not even require registration with the operating system. これにより、ランタイムが使用する記述は常にコンパイル済みファイル内の実際のコードに反映されるため、アプリケーションの信頼性が高くなります。As a result, the descriptions used by the runtime always reflect the actual code in your compiled file, which increases application reliability.

  • 言語の相互運用性と簡単なコンポーネント ベースのデザインLanguage interoperability and easier component-based design.

    メタデータは、他の言語で記述されている PE ファイルからクラスを継承するのに必要な、コンパイル済みコードについてのすべての情報を提供します。Metadata provides all the information required about compiled code for you to inherit a class from a PE file written in a different language. 明示的なマーシャリングや相互運用可能なカスタム コードの使用を考慮せずに、マネージド言語 (共通言語ランタイムに変換される言語) で記述された任意のクラスのインスタンスを作成できます。You can create an instance of any class written in any managed language (any language that targets the common language runtime) without worrying about explicit marshaling or using custom interoperability code.

  • 属性。Attributes.

    .NET Framework を使用すると、コンパイル済みファイル内で "属性" と呼ばれる特定の種類のメタデータを宣言できます。The .NET Framework lets you declare specific kinds of metadata, called attributes, in your compiled file. 属性は、.NET Framework 全体で使用され、実行時のプログラムの動作を詳細に制御します。Attributes can be found throughout the .NET Framework and are used to control in more detail how your program behaves at run time. また、ユーザー定義のカスタム属性によって、独自に作成したメタデータを .NET Framework のファイルに挿入できます。Additionally, you can emit your own custom metadata into .NET Framework files through user-defined custom attributes. 詳細については、「属性」を参照してください。For more information, see Attributes.

メタデータと PE ファイルの構造Metadata and the PE File Structure

メタデータと Microsoft Intermediate Language (MSIL) は、それぞれ、.NET Framework のポータブル実行可能 (PE) ファイルの別のセクションに格納されます。Metadata is stored in one section of a .NET Framework portable executable (PE) file, while Microsoft intermediate language (MSIL) is stored in another section of the PE file. ファイルのメタデータ部分には、一連のテーブルとヒープ データの構造が格納されています。The metadata portion of the file contains a series of table and heap data structures. MSIL 部分には、PE ファイルのメタデータ部分を参照する MSIL とメタデータ トークンが格納されています。The MSIL portion contains MSIL and metadata tokens that reference the metadata portion of the PE file. コードの MSIL を表示する MSIL 逆アセンブラー (Ildasm.exe) のようなツールを使用すると、メタデータ トークンが表示される場合があります。You might encounter metadata tokens when you use tools such as the MSIL Disassembler (Ildasm.exe) to view your code's MSIL, for example.

メタデータのテーブルおよびヒープMetadata Tables and Heaps

各メタデータ テーブルには、プログラムの要素に関する情報が保持されています。Each metadata table holds information about the elements of your program. たとえば、1 つのメタデータ テーブルにはコード内のクラスが記述されており、別のテーブルにはフィールドが記述されています。For example, one metadata table describes the classes in your code, another table describes the fields, and so on. コードに 10 個のクラスが存在する場合、クラス テーブルには、各クラスごとに 1 行、つまり 10 行が存在します。If you have ten classes in your code, the class table will have tens rows, one for each class. メタデータ テーブルは、他のテーブルおよびヒープを参照します。Metadata tables reference other tables and heaps. たとえば、クラスのメタデータ テーブルは、メソッドのテーブルを参照します。For example, the metadata table for classes references the table for methods.

また、メタデータは、4 つのヒープ構造 (文字列、BLOB、ユーザー文字列、および GUID) に情報を格納します。Metadata also stores information in four heap structures: string, blob, user string, and GUID. 型やメンバーに名前を付けるために使用する文字列はすべて、文字列ヒープに格納されています。All the strings used to name types and members are stored in the string heap. たとえば、特定のメソッドの名前はメソッド テーブルに直接は格納されず、メソッド テーブルから文字列ヒープ内に格納されているメソッドの名前を参照します。For example, a method table does not directly store the name of a particular method, but points to the method's name stored in the string heap.

メタデータ トークンMetadata Tokens

各メタデータ テーブルのそれぞれの行は、メタデータ トークンによって、PE ファイルの MSIL 部分内で一意に識別されます。Each row of each metadata table is uniquely identified in the MSIL portion of the PE file by a metadata token. メタデータ トークンは、概念上、ポインターに類似しており、特定のメタデータ テーブルを参照します。Metadata tokens are conceptually similar to pointers, persisted in MSIL, that reference a particular metadata table.

メタデータ トークンは、4 バイトで構成される数値です。A metadata token is a four-byte number. 最上位バイトは、特定のトークンの参照先であるメタデータ テーブル (メソッド、型など) を表します。The top byte denotes the metadata table to which a particular token refers (method, type, and so on). 残り 3 バイトは、記述されているプログラミング要素と対応する、メタデータ テーブル内の行を指定します。The remaining three bytes specify the row in the metadata table that corresponds to the programming element being described. たとえば、C# 言語でメソッドを定義し、そのメソッドを PE ファイルとしてコンパイルすると、PE ファイルの MSIL 部分に次のようなメタデータ トークンが格納されます。If you define a method in C# and compile it into a PE file, the following metadata token might exist in the MSIL portion of the PE file:

0x06000004

最上位バイト (0x06) は、MethodDef トークンであることを示します。The top byte (0x06) indicates that this is a MethodDef token. 下位 3 バイト (000004) は、MethodDef テーブル内の、このメソッドの定義を記述する情報に対応する 4 行目を参照するように、共通言語ランタイムに指示します。The lower three bytes (000004) tells the common language runtime to look in the fourth row of the MethodDef table for the information that describes this method definition.

PE ファイル内のメタデータMetadata within a PE File

プログラムを共通言語ランタイムとしてコンパイルすると、プログラムは 3 つの部分で構成される PE ファイルに変換されます。When a program is compiled for the common language runtime, it is converted to a PE file that consists of three parts. 各部分の内容を説明する表を次に示します。The following table describes the contents of each part.

PE セクションPE section PE セクションの内容Contents of PE section
PE ヘッダーPE header PE ファイルの主要なセクションのインデックスとエントリ ポイントのアドレス。The index of the PE file's main sections and the address of the entry point.

ランタイムはこの情報に基づいてファイルを PE ファイルとして識別し、実行開始位置と、メモリにプログラムをいつ読み込むかを判断します。The runtime uses this information to identify the file as a PE file and to determine where execution starts when loading the program into memory.
MSIL の命令MSIL instructions コードを構成する Microsoft Intermediate Language (MSIL) の命令。The Microsoft intermediate language instructions (MSIL) that make up your code. ほとんどの MSIL 命令には、メタデータ トークンが付いています。Many MSIL instructions are accompanied by metadata tokens.
メタデータMetadata メタデータ テーブルおよびヒープ。Metadata tables and heaps. ランタイムはこのセクションを使用してコード内のすべての型およびメンバーに関する情報を記録します。The runtime uses this section to record information about every type and member in your code. また、このセクションには、カスタム属性やセキュリティ情報も格納されています。This section also includes custom attributes and security information.

実行時のメタデータの使用Run-Time Use of Metadata

メタデータと、共通言語ランタイムでのメタデータの役割をより深く理解するために、簡単なプログラムを作成し、メタデータがその有効期間中にどのように機能するかを示します。To better understand metadata and its role in the common language runtime, it might be helpful to construct a simple program and illustrate how metadata affects its run-time life. MyApp と呼ばれるクラス内の 2 つのメソッドを表すコードの例を次に示します。The following code example shows two methods inside a class called MyApp. Main メソッドは、プログラムのエントリ ポイントです。Add メソッドは、2 つの整数引数の合計値を返します。The Main method is the program entry point, while the Add method simply returns the sum of two integer arguments.

Public Class MyApp
   Public Shared Sub Main()
      Dim ValueOne As Integer = 10
      Dim ValueTwo As Integer = 20
      Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo))
   End Sub

   Public Shared Function Add(One As Integer, Two As Integer) As Integer
      Return (One + Two)
   End Function
End Class
using System;
public class MyApp
{
   public static int Main()
   {
      int ValueOne = 10;
      int ValueTwo = 20;
      Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo));
      return 0;
   }
   public static int Add(int One, int Two)
   {
      return (One + Two);
   }
}

このコードを実行すると、ランタイムがモジュールをメモリに読み込み、このクラスのメタデータを調べます。When the code runs, the runtime loads the module into memory and consults the metadata for this class. モジュールを読み込んだ後、ランタイムはメソッドの Microsoft Intermediate Language (MSIL) ストリームを詳細に分析して、そのストリームを高速のネイティブ機械語命令に変換します。Once loaded, the runtime performs extensive analysis of the method's Microsoft intermediate language (MSIL) stream to convert it to fast native machine instructions. ランタイムはジャスト イン タイム (JIT) コンパイラを使用して、それぞれのメソッドを必要なときに 1 つずつ、MSIL 命令からネイティブ マシン語コードに変換します。The runtime uses a just-in-time (JIT) compiler to convert the MSIL instructions to native machine code one method at a time as needed.

上記のコードの Main 関数によって生成された MSIL の一部の例を次に示します。The following example shows part of the MSIL produced from the previous code's Main function. MSIL とメタデータは、MSIL 逆アセンブラー (Ildasm.exe) を使用することにより、任意の .NET Framework アプリケーションから表示できます。You can view the MSIL and metadata from any .NET Framework application using the MSIL Disassembler (Ildasm.exe).

.entrypoint
.maxstack  3
.locals ([0] int32 ValueOne,
         [1] int32 ValueTwo,
         [2] int32 V_2,
         [3] int32 V_3)
IL_0000:  ldc.i4.s   10
IL_0002:  stloc.0
IL_0003:  ldc.i4.s   20
IL_0005:  stloc.1
IL_0006:  ldstr      "The Value is: {0}"
IL_000b:  ldloc.0
IL_000c:  ldloc.1
IL_000d:  call int32 ConsoleApplication.MyApp::Add(int32,int32) /* 06000003 */

JIT コンパイラはこのメソッド全体の MSIL を読み取って詳細に分析し、このメソッドの効率的なネイティブ命令を生成します。The JIT compiler reads the MSIL for the whole method, analyzes it thoroughly, and generates efficient native instructions for the method. IL_000d で、Add メソッドのメタデータ トークン (/* 06000003 */) が検出されます。ランタイムは、このトークンを使用して MethodDef テーブルの 3 行目を調べます。At IL_000d, a metadata token for the Add method (/* 06000003 */) is encountered and the runtime uses the token to consult the third row of the MethodDef table.

メソッドが記述されているメタデータ トークンによって参照される、 MethodDefAdd テーブルの一部の例を次の表に示します。The following table shows part of the MethodDef table referenced by the metadata token that describes the Add method. このアセンブリにはほかにもメタデータ テーブルが存在し、それぞれ独自の値を持っていますが、ここでは、このテーブルだけを参照します。While other metadata tables exist in this assembly and have their own unique values, only this table is discussed.

Row Relative Virtual Address (RVA)Relative Virtual Address (RVA) ImplFlagsImplFlags フラグFlags nameName

(文字列ヒープを指す)(Points to string heap.)
Signature (BLOB ヒープを指す)Signature (Points to blob heap.)
11 0x000020500x00002050 ILIL

マネージドManaged
PublicPublic

ReuseSlotReuseSlot

SpecialNameSpecialName

RTSpecialNameRTSpecialName

.ctor.ctor
.ctor (コンストラクター).ctor (constructor)
22 0x000020580x00002058 ILIL

マネージドManaged
PublicPublic

スタティックStatic

ReuseSlotReuseSlot
メインMain StringString
33 0x0000208c0x0000208c ILIL

マネージドManaged
PublicPublic

スタティックStatic

ReuseSlotReuseSlot
追加Add int, int, intint, int, int

このテーブルの各列には、コードについての重要な情報が格納されています。Each column of the table contains important information about your code. ランタイムは RVA 列を使用して、このメソッドを定義する MSIL の開始メモリ アドレスを計算します。The RVA column allows the runtime to calculate the starting memory address of the MSIL that defines this method. ImplFlags および Flags 列には、このメソッドを記述するビットマスク (たとえば、メソッドがパブリックかプライベートかを記述するビットマスク) が格納されています。The ImplFlags and Flags columns contain bitmasks that describe the method (for example, whether the method is public or private). Name 列は、文字列ヒープからメソッドの名前へのインデックスとなります。The Name column indexes the name of the method from the string heap. Signature 列は、BLOB ヒープ内のメソッドのシグネチャ定義へのインデックスとなります。The Signature column indexes the definition of the method's signature in the blob heap.

ランタイムは 3 行目の RVA 列から必要なオフセット アドレスを計算し、計算したオフセット アドレスを JIT コンパイラに返します。JIT コンパイラは計算された新しいアドレスに移動します。The runtime calculates the desired offset address from the RVA column in the third row and returns this address to the JIT compiler, which then proceeds to the new address. JIT コンパイラは、新しいアドレスから、別のメタデータ トークンを検出するまで MSIL の処理を続行し、処理を繰り返します。The JIT compiler continues to process MSIL at the new address until it encounters another metadata token and the process is repeated.

ランタイムは、メタデータを使用することにより、コードを読み込み、ネイティブ機械語命令に変換するのに必要なすべての情報にアクセスできます。Using metadata, the runtime has access to all the information it needs to load your code and process it into native machine instructions. このように、メタデータによって自己言及的なファイルが使用可能になり、メタデータと共通型システムを組み合わせて使用することで、言語間で継承が可能になります。In this manner, metadata enables self-describing files and, together with the common type system, cross-language inheritance.

TitleTitle 説明Description
属性Attributes 属性の適用方法、カスタム属性の記述方法、および属性に格納されている情報の取得方法を説明します。Describes how to apply attributes, write custom attributes, and retrieve information that is stored in attributes.