Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В прошлом программный компонент (EXE или DLL), написанный на одном языке, не мог просто так использовать программный компонент, написанный на другом языке. Модель COM стала шагом вперед в решении этой проблемы. Платформа .NET упрощает взаимодействие компонентов, позволяя компиляторам добавлять дополнительные описательные данные во все модули и сборки. Эти данные, называемые метаданными, способствуют эффективному взаимодействию компонентов.
Метаданные — это данные в двоичном формате с описанием программы, хранящиеся либо в переносимом исполняемом (PE) файле среды CLR, либо в памяти. При компиляции кода в PE-файл метаданные вставляются в одну часть файла, и код преобразуется в общий промежуточный язык (CIL) и вставляется в другую часть файла. В метаданных описываются все типы и члены, определенные или используемые в модуле или сборке. При исполнении кода среда выполнения загружает метаданные в память и обращается к ним для получения сведений о классах, членах, наследовании и других элементах кода.
В метаданных в независимом от языка виде описываются все типы и члены, определенные в коде. В метаданных хранятся следующие сведения.
Описание сборки.
Идентификатор (имя, версия, культура, открытый ключ).
Экспортируемые типы.
Другие сборки, от которых зависит данная сборка.
Необходимы разрешения безопасности для выполнения.
Описание типов.
Имя, видимость, базовый класс и реализованные интерфейсы.
Члены (методы, поля, свойства, события, вложенные типы).
Атрибуты.
- Дополнительные описательные элементы, изменяющие типы и члены.
Преимущества метаданных
Метаданные — это ключ к более простой модели программирования; они устраняют необходимость в файлах IDL, файлах заголовков или каких-либо внешних методах ссылки на компоненты. Метаданные позволяют языкам платформы .NET автоматически описывать себя не зависящим от языка образом незаметно для разработчика и пользователя. К тому же метаданные имеют возможности для расширения за счет использование атрибутов. Метаданные обеспечивают также следующие преимущества.
Самоописывающиеся файлы.
Модули и сборки среды выполнения Common Language Runtime (CLR) обладают свойством самоописания. Метаданные модуля содержат все необходимое для взаимодействия с другим модулем. Метаданные автоматически предоставляют функциональные возможности IDL для модели СОМ, в связи с чем один и тот же файл может использоваться и для определения, и для реализации. Модули и сборки среды выполнения даже не требуют регистрации в операционной системе. Благодаря этому описания, используемые средой выполнения, всегда отражают фактический код в скомпилированном файле, что повышает надежность приложения.
Взаимодействие языков и упрощение разработки на основе компонентов
Метаданные содержат полные сведения о скомпилированном коде, необходимые для наследования класса из PE-файла, написанного на другом языке. Вы можете создать экземпляр любого класса, написанного на любом управляемом языке (любой язык, предназначенный для среды CLR), не беспокоясь о явном маршаллинге или использовании пользовательского кода взаимодействия.
Атрибуты.
Платформа .NET позволяет объявлять особые виды метаданных, называемые атрибутами, в скомпилированном файле. Атрибуты можно найти в .NET и использовать для более подробного управления поведением программы во время выполнения. Также с помощью атрибутов в файлы .NET можно вносить пользовательские метаданные, определяемые самим пользователем. Дополнительные сведения см. в разделе Атрибуты.
Метаданные и структура PE-файла
Метаданные хранятся в одном разделе переносимого исполняемого файла .NET (PE), а общий промежуточный язык (CIL) хранится в другом разделе PE-файла. Раздел файла с метаданными содержит ряд табличных структур и структуры кучи данных. Часть CIL содержит маркеры CIL и метаданных, ссылающиеся на часть метаданных pe-файла. При использовании таких средств, как IL Disassembler (Ildasm.exe) для просмотра кода CIL, вы можете столкнуться с маркерами метаданных.
Таблицы и кучи метаданных
Каждая таблица метаданных содержит сведения об элементах программы. К примеру, в одной таблице метаданных описываются классы в коде, в другой — поля и так далее. Если в коде используется десять классов, таблица классов будет содержать десять строк, по одной для каждого класса. Таблицы метаданных ссылаются на другие таблицы и кучи. Например, таблица метаданных для классов ссылается на таблицу методов.
В метаданных сведения также хранятся в четырех структурах кучи: в куче строк, в куче больших двоичных объектов, в куче пользовательских строк и в куче глобальных уникальных идентификаторов (GUID). Все строки, используемые для названия типов и членов, хранятся в куче строк. Например, в таблице методов не хранится имя конкретного метода, но содержится ссылка на имя этого метода, находящееся в куче строк.
Лексемы метаданных
Каждая строка каждой таблицы метаданных однозначно определяется в части CIL-файла PE маркером метаданных. Маркеры метаданных концептуально похожи на указатели, сохраняемые в CIL, ссылающиеся на определенную таблицу метаданных.
Лексема метаданных является четырехбайтным числом. Старший байт указывает на таблицу метаданных, к которой относится данная лексема (метод, тип и т. д.). Остальные три байта определяют строку в таблице метаданных, которая соответствует описываемому программному элементу. Если определить метод в C# и скомпилировать его в PE-файл, в части CIL файла PE может существовать следующий маркер метаданных:
0x06000004
Старший байт (0x06) указывает, что это лексема MethodDef. Три младших байта (000004) указывают общей языковой среде выполнения искать в четвертой строке таблицы MethodDef для получения сведений, описывающих определение метода.
Метаданные внутри PE-файла
После компиляции программы для среды CLR она преобразуется в PE-файл, состоящий из трех разделов. В следующей таблице описано содержание каждого раздела.
| Раздел PE | Содержание раздела PE |
|---|---|
| Заголовок PE-файла | Индекс основных разделов PE-файла и адрес точки входа. Среда выполнения использует эти сведения для определения файла как PE-файла и определения начала выполнения при загрузке программы в память. |
| Инструкции CIL | Инструкции промежуточного языка Microsoft (CIL), составляющие ваш код. Многие инструкции CIL сопровождаются маркерами метаданных. |
| Метаданные | Таблицы и кучи метаданных Среда выполнения использует этот раздел для записи сведений о каждом типе и члене в коде. Этот раздел также содержит пользовательские атрибуты и сведения о безопасности. |
Использование метаданных во время выполнения
Чтобы лучше понять метаданные и их роль в среде CLR, может быть полезно создать простую программу и продемонстрировать, как метаданные влияют на время выполнения программы. В приведенном ниже примере показано два метода внутри класса MyApp. Метод Main является точкой входа программы, а метод Add — просто возвращает сумму двух целочисленных аргументов.
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);
}
}
При запуске кода среда выполнения загружает модуль в память и обращается к метаданным за сведениями об этом классе. После загрузки среда выполнения выполняет обширный анализ потока общего промежуточного языка метода (CIL), чтобы преобразовать его в быстрые инструкции машинного компьютера. Среда выполнения использует JIT-компилятор для преобразования инструкций CIL в машинный код по мере необходимости, обрабатывая при этом один метод за раз.
В следующем примере показана часть CIL, созданная из функции предыдущего кода Main . Вы можете просмотреть CIL и метаданные из любого приложения .NET с помощью il 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 считывает CIL для всего метода, тщательно анализирует его и создает эффективные собственные инструкции для метода. В строке IL_000d появляется маркер метаданных для метода Add (/*06000003 */), и среда выполнения использует этот маркер для обращения к третьей строке таблицы MethodDef.
В приведенной ниже таблице показана часть таблицы MethodDef, на которую ссылается лексема метаданных, описывающая метод Add. В сборке существуют и другие таблицы метаданных со своими уникальными значениями, но в данный момент рассматривается только эта таблица.
| Ряд | Относительный виртуальный адрес (RVA) | Неявные флаги | Флаги | Имя. (Указывает на кучу строк.) |
Сигнатура (указывает на blob-кучу) |
|---|---|---|---|---|---|
| 1 | 0x00002050 | Иллинойс Управляется |
Общедоступный ReuseSlot SpecialName RTSpecialName .ctor |
.ctor (конструктор) | |
| 2 | 0x00002058 | Иллинойс Управляется |
Общедоступный Статический ReuseSlot |
Главная | Строка |
| 3 | 0x0000208c | Иллинойс Управляется |
Общедоступный Статический ReuseSlot |
Добавить | int, int, int |
В каждом столбце таблицы содержатся важные сведения о коде. Столбец RVA позволяет среде выполнения вычислять начальный адрес памяти CIL, который определяет этот метод. Столбцы Неявные флаги и Флаги содержат битовые маски, описывающие метод (например, является ли метод общим или закрытым). Столбец Имя содержит указатель имени метода из кучи строк. Столбец Сигнатура индексирует определение сигнатуры метода в куче блобов.
Среда выполнения вычисляет нужный относительный адрес из столбца RVA в третьей строке и возвращает этот адрес JIT-компилятору, который затем переходит к новому адресу. Компилятор JIT продолжает обрабатывать CIL на новом адресе, пока не столкнется с другим маркером метаданных и процесс повторяется.
Благодаря метаданным среда выполнения имеет доступ к любым сведениям, необходимым для загрузки кода пользователя и его преобразования в инструкции машинного кода. Таким образом, метаданные позволяют использовать файлы с самоописанием и — совместно с системой общих типов — межъязыковое наследование.