Метаданные и компоненты с самоописаниемMetadata and Self-Describing Components

В прошлом программный компонент (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) файле среды CLR, либо в памяти.Metadata is binary information describing your program that is stored either in a common language runtime portable executable (PE) file or in memory. Когда код компилируется в PE-файл, метаданные помещаются в одну часть файла, а код преобразуется в MSIL и помещается в другую часть файла.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.

    • Удостоверение (имя, версия, язык и региональные параметры, открытый ключ).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, файлах заголовков или каких-либо внешних методах ссылки на компоненты.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.

    Модули среды CLR и сборки обладают свойством самоописания.Common language runtime modules and assemblies are self-describing. Метаданные модуля содержат все необходимое для взаимодействия с другим модулем.A module's metadata contains everything needed to interact with another module. Метаданные автоматически предоставляют функциональные возможности IDL для модели СОМ, в связи с чем один и тот же файл может использоваться и для определения, и для реализации.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. Можно создать экземпляр класса, написанного на любом другом управляемом языке (это может быть любой язык, обращающийся к среде CLR), не беспокоясь о явной упаковке или настройке кода взаимодействия.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

Метаданные хранятся в одном разделе переносимого исполняемого (PE) файла .NET Framework, а код на промежуточном языке MSIL хранится в другом его разделе.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 содержит код MSIL и лексемы метаданных, ссылающиеся на раздел метаданных PE-файла.The MSIL portion contains MSIL and metadata tokens that reference the metadata portion of the PE file. При использовании таких средств, как дизассемблер MSIL (Ildasm.exe), для просмотра MSIL-кода можно обнаружить токены метаданных.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. К примеру, в одной таблице метаданных описываются классы в коде, в другой — поля и так далее.For example, one metadata table describes the classes in your code, another table describes the fields, and so on. Если в коде используется десять классов, таблица классов будет содержать десять строк, по одной для каждого класса.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.

В метаданных сведения также хранятся в четырех структурах кучи — в куче строк, больших двоичных объектов, пользовательских строк и идентификаторов 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

Каждая строка любой таблицы метаданных уникально идентифицируется в разделе MSIL PE-файла с помощью лексемы метаданных.Each row of each metadata table is uniquely identified in the MSIL portion of the PE file by a metadata token. Лексемы метаданных по своей сути похожи на указатели, сохраненные в MSIL, которые ссылаются на определенную таблицу метаданных.Metadata tokens are conceptually similar to pointers, persisted in MSIL, that reference a particular metadata table.

Лексема метаданных является четырехбайтным числом.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). Остальные три байта определяют строку в таблице метаданных, которая соответствует описываемому программному элементу.The remaining three bytes specify the row in the metadata table that corresponds to the programming element being described. Если определить метод в языке C# и скомпилировать его в PE-файл, то в разделе MSIL PE-файла может появиться следующая лексема метаданных: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. Три младших байта (000004) отсылают среду CLR к четвертой строке таблицы MethodDef для получения сведений с описанием определения метода.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

После компиляции программы для среды CLR она преобразуется в 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
Заголовок PEPE 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.
Инструкции MSILMSIL instructions Инструкции промежуточного языка 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

Для лучшего понимания метаданных и их роли в среде CLR полезно написать простую программу и наглядно проиллюстрировать, как метаданные влияют на работу среды выполнения.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.The following code example shows two methods inside a class called MyApp. Метод Main является точкой входа программы, а метод Add — просто возвращает сумму двух целочисленных аргументов.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. После загрузки среда выполнения проводит подробный анализ потока кода 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. В среде выполнения для преобразования инструкций MSIL в исходный машинный код используется JIT-компилятор. Преобразование выполняется по одному методу за раз по мере необходимости.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.

В приведенном ниже примере показана часть кода MSIL, полученного для функции Main из предыдущего кода.The following example shows part of the MSIL produced from the previous code's Main function. Код MSIL и метаданные любого приложения .NET Framework можно просмотреть при помощи дизассемблера MSIL (Ildasm.exe).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.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.

В приведенной ниже таблице показана часть таблицы MethodDef, на которую ссылается лексема метаданных, описывающая метод Add.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 Относительный виртуальный адрес (RVA)Relative Virtual Address (RVA) Неявные флагиImplFlags ФлагиFlags nameName

(Указывает на кучу строк.)(Points to string heap.)
Сигнатура (указывает на кучу больших двоичных объектов)Signature (Points to blob heap.)
11 0x000020500x00002050 ILIL

УправляемыйManaged
PublicPublic

ReuseSlotReuseSlot

SpecialNameSpecialName

RTSpecialNameRTSpecialName

.ctor.ctor
.ctor (конструктор).ctor (constructor)
22 0x000020580x00002058 ILIL

УправляемыйManaged
PublicPublic

StaticStatic

ReuseSlotReuseSlot
Главная ветвьMain StringString
33 0x0000208c0x0000208c ILIL

УправляемыйManaged
PublicPublic

StaticStatic

ReuseSlotReuseSlot
AddAdd 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. Столбцы Неявные флаги и Флаги содержат битовые маски, описывающие метод (например, является ли метод общим или закрытым).The ImplFlags and Flags columns contain bitmasks that describe the method (for example, whether the method is public or private). Столбец Имя содержит указатель имени метода из кучи строк.The Name column indexes the name of the method from the string heap. Столбец Сигнатура содержит указатель определения сигнатуры метода в куче больших двоичных объектов.The Signature column indexes the definition of the method's signature in the blob heap.

Среда выполнения вычисляет нужный относительный адрес из столбца RVA в третьей строке и возвращает этот адрес 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.

ЗаголовокTitle ОписаниеDescription
АтрибутыAttributes Описание способов применения атрибутов, написания настраиваемых атрибутов и извлечения данных, хранящихся в атрибутах.Describes how to apply attributes, write custom attributes, and retrieve information that is stored in attributes.