Метаданные в Common Language Infrastructure (CLI) относятся к определенным структурам данных, встроенным в код Common Intermediate Language (CIL), который описывает высокоуровневую структуру кода. Метаданные описывают все классы и члены классов, которые определены в сборке, а также классы и члены классов , которые текущая сборка будет вызывать из другой сборки. Метаданные для метода содержат полное описание метода, включая класс (и сборку, содержащую класс), тип возвращаемого значения и все параметры метода .
Компилятор языка CLI сгенерирует метаданные и сохранит их в сборке, содержащей CIL . Когда среда выполнения выполняет CIL , она проверит, совпадают ли метаданные вызываемого метода с метаданными, хранящимися в вызывающем методе. Это гарантирует, что метод может быть вызван только с точно правильным количеством параметров и точно правильными типами параметров.
Платформа приложений Windows Runtime , представленная в Windows 8 и Windows Phone 8 , использует формат метаданных CLI для описания интерфейсов компонентов для кода, написанного на любом из поддерживаемых языков программирования . Отличие в использовании в Common Language Runtime заключается в том, что сборка обычно не содержит никаких инструкций CIL. [1]
Разработчики могут добавлять метаданные в свой код через атрибуты . Существует два типа атрибутов: пользовательские и псевдопользовательские атрибуты, и для разработчика они имеют одинаковый синтаксис . Атрибуты в коде — это сообщения компилятору для генерации метаданных. В CIL метаданные, такие как модификаторы наследования, модификаторы области действия и почти все, что не является ни кодами операций, ни потоками, также называются атрибутами.
Пользовательский атрибут — это обычный класс , который наследуется от Attribute
класса. Пользовательский атрибут может использоваться в любом методе, свойстве, классе или всей сборке с синтаксисом: как в:[AttributeName(optional parameter, optional name=value pairs)]
[Пользовательский] [Пользовательский(1)] [Пользовательский(1, Комментарий="да")]
Пользовательские атрибуты широко используются CLI. Windows Communication Framework использует атрибуты для определения контрактов служб, ASP.NET использует их для предоставления методов в качестве веб-служб , LINQ to SQL использует их для определения сопоставления классов с базовой реляционной схемой , Visual Studio использует их для группировки свойств объекта, разработчик класса указывает категорию для класса объекта, применяя [Category]
пользовательский атрибут. Пользовательские атрибуты интерпретируются кодом приложения, а не CLR. Когда компилятор видит пользовательский атрибут, он генерирует пользовательские метаданные, которые не распознаются CLR. Разработчик должен предоставить код для чтения метаданных и действия с ними. Например, атрибут, показанный в примере, может быть обработан кодом:
class CustomAttribute : Attribute { private int paramNumber = 0 ; private string comment = "" ; public CustomAttribute () { } public CustomAttribute ( int num ) { paramNumber = num ; } публичный строковый комментарий { set { comment = value ; } } }
Имя класса сопоставляется с именем атрибута. Компилятор Visual C# автоматически добавляет строку " Attribute
" в конец любого имени атрибута. Следовательно, каждое имя класса атрибута должно заканчиваться этой строкой, но допустимо определять атрибут без суффикса Attribute
-. При присоединении атрибута к элементу компилятор будет искать как буквальное имя, так и имя с Attribute
добавленным в конец, т. е. если бы вы написали , [Custom]
компилятор искал бы и Custom
, и CustomAttribute
. Если существуют оба, компилятор завершается ошибкой. Атрибут может быть снабжен префиксом " @
", если вы не хотите рисковать неоднозначностью, поэтому запись [@Custom]
не будет соответствовать CustomAttribute
. Использование атрибута вызывает конструктор класса. Поддерживаются перегруженные конструкторы. Пары Имя-Значение сопоставляются со свойствами, имя обозначает имя свойства, а предоставленное значение устанавливается свойством.
Иногда возникает двусмысленность относительно того, что вы прикрепляете к атрибуту. Рассмотрим следующий код:
[Orange] public int ExampleMethod ( string input ) { //здесь размещается тело метода }
Что отмечено как оранжевый? Это ExampleMethod
, его возвращаемое значение или, возможно, вся сборка? В этом случае компилятор будет использовать значение по умолчанию и рассматривать атрибут как прикрепленный к методу. Если это не то, что предполагалось, или если автор хочет прояснить свой код, можно указать целевой атрибут[return: Orange]
. Writing отметит возвращаемое значение как оранжевый, [assembly: Orange]
отметит всю сборку. Допустимые цели: assembly
, field
, event
, method
, module
, param
, property
, return
и type
.
Псевдопользовательский атрибут используется так же, как и обычные пользовательские атрибуты, но у них нет пользовательского обработчика; вместо этого компилятор имеет внутреннюю осведомленность об атрибутах и обрабатывает код, помеченный такими атрибутами, по-разному. Такие атрибуты, как Serializable
и Obsolete
реализованы как псевдопользовательские атрибуты. Псевдопользовательские атрибуты никогда не должны использоваться ILAsm , поскольку он имеет адекватный синтаксис для описания метаданных. [ необходимо разъяснение ]
Сборки содержат таблицы метаданных. Эти таблицы описаны спецификацией CIL. Таблицы метаданных будут иметь ноль или более записей, а положение записи определяет ее индекс. Когда код CIL использует метаданные, он делает это через токен метаданных. Это 32- битное значение, где верхние 8 бит идентифицируют соответствующую таблицу метаданных, а оставшиеся 24 бита дают индекс метаданных в таблице. Framework SDK содержит пример под названием metainfo
, который будет перечислять таблицы метаданных в сборке, однако эта информация редко бывает полезна разработчику. Метаданные в сборке можно просматривать с помощью инструмента ILDASM, предоставляемого .NET Framework SDK.
В стандарте CIL метаданные определяются в форме ILAsm (язык ассемблера), форме представления на диске для хранения и форме, которая встроена в сборки формата Portable Executable (PE, .exe или .dll). Форма PE основана на форме на диске.
Reflection — это API, используемый для чтения метаданных CLI. Reflection API обеспечивает логическое представление метаданных, а не буквальное представление, предоставляемое такими инструментами, как metainfo. Reflection в версии 1.1 фреймворка .NET может использоваться для проверки описаний классов и их членов, а также для вызова методов. Однако он не позволяет осуществлять доступ к CIL для метода во время выполнения. Версия 2.0 фреймворка позволяет получать CIL для метода.
Помимо System.Reflection
пространства имен, также доступны другие инструменты, которые можно использовать для обработки метаданных. Microsoft .NET Framework поставляет библиотеку манипуляции метаданными CLR, которая реализована в машинном коде . Также можно использовать сторонние инструменты для извлечения и манипулирования метаданными, включая PostSharp и Mono Cecil.