Основные метаданные модуля хранятся в виде набора таблиц. В одной из них — TypeDef — перечислены определенные в этом модуле типы. (Тип — это общий термин, обозначающий классы, структуры, перечисления и иные формы данных, поддерживаемые CLR). В другой таблице перечислены методы, реализованные этими типами, в третьей — поля, в четвертой — свойства и т. д. Используя эти таблицы, можно составить список всех типов данных, определенных в модуле, а также членов, из которых состоит каждый тип. В некоторых таблицах перечислены ссылки на внешние типы (типы и члены типов в других модулях, используемые данным модулем), сборки, содержащие внешние типы, и др.
Дополнительная информация метаданных хранится вне таблиц в кучах, содержащих элементы, на которые ссылаются записи в таблицах. Так, имена классов и методов хранятся в строковой куче, а строковые литералы — в отдельной пользовательской строковой куче. Вместе таблицы и кучи метаданных содержат все сведения о модуле, его содержимом и внешних зависимостях, которые могут понадобиться вам (или CLR).
Маркеры метаданных (metadata tokens), ссылающиеся на записи в таблицах метаданных, разбросаны повсюду в той части управляемого модуля, что содержит CIL. Каждая запись в любой таблице может быть указана 32-разрядным маркером метаданных, состоящим из 8-разрядного индекса таблицы и 24-разрядного индекса записи. При генерации CIL для метода компилятор также порождает маркер метаданных, ссылающийся на запись со сведениями о данном методе. Встретив маркер, CLR может, обратившись к соответствующей записи, узнать имя метода, его видимость, сигнатуру и даже адрес памяти.
Формат метаданных интересен с академической точки зрения, но разработчику в нем обычно нет нужды. Большинство приложений не работает с метаданными напрямую, а предоставляет эту работу CLR и компилятору. Приложения, которым нужно считывать и генерировать метаданные, могут делать это с помощью одного из двух API, предоставляемых .NET Framework. Эти API отражения (reflection API) изолируют разработчика от двоичного формата метаданных. Один из них — это неуправляемый API, реализованный в виде СОМ-интерфейсов. Другой — управляемый API, реализованный классами FCL из пространства имен SystemMeflection.
С помощью API отражения довольно легко написать утилиту, выводящую список типов управляемого модуля и их члены. Однако писать утилиту для отображения метаданных не надо — она уже есть в .NET Framework SDK: утилита ILDASM использует отражение для отображения содержимого управляемых исполняемых файлов. На рис. 1-1 ILDASM отображает ImageView.exe — один из примеров программ главы 4. В дереве показан один определенный в модуле класс (MyForm) и все члены этого класса. Если же запустить ILDASM с ключом /ADV («Advanced») и выбрать команду View/Metalnfo/Show (или нажать комбинацию клавиш Ctrl+M, которая работает независимо от наличия ключа /ADV), на экране появится окно со всеми записями таблиц метаданных (рис. 1-2). Меню View/Metalnfo позволяет выбирать разные режимы отображения метаданных.
Puc. 1-1. Отображение ImageView.exe утилитой ILDASM
Puc. 1-2. Отображение метаданных с помощью ILDASM
Похожие статьи: