Метаданные в C#

Давайте внимательнее рассмотрим пример “Hello World!” и сравним его с тем, что вы могли бы делать, если пришли из мира С++. Для начала обратите внимание, что здесь нет никаких включений заголовков. Причина в том, что С# в этом не нуждается. Взамен используется нечто более надежное и информативное, а именно — метаданные. За счет применения метаданных управляемые модули являются самоописательными.

1
2
3
4
class EntryPoint {
static void Main()  {
System.Console.WriteLine ( "Hello World!" );
}

В мире С++ для подключения библиотеки к приложению нужны две веши: статическая библиотека или DLL и обычно заголовочный файл.

Поскольку они существуют как две отдельные сущности, которые должны трактоваться как одно целое, вполне возможно, что заголовочный файл окажется не соответствующим библиотеке, если не проявить должную осторожность. Это может привести к неприятностям. Управляемые модули, с другой стороны, содержат всю необходимую информацию внутри метаданных, находящихся в самом модуле.

Единицей повторного использования в управляемом мире является сборка, и сборки могут состоять из множества модулей. Таким образом, сборка, фактически, самодостаточна.

Метаданные также являются расширяемыми, что позволяет определять новые типы и атрибуты, которые могут содержаться в метаданных. И в завершение следует отметить, что доступ к метаданным возможен во время выполнения. Например, во время выполнения можно пройти по всем полям произвольного типа класса, не зная его объявления заранее, перед компиляцией.

Сообразительный читатель поймет, что это открывает возможность генерации целых программ и типов во время выполнения, что также совершенно невозможно в родном С++, если только не встроить в приложение полный компилятор С++.

Метаданные — это расширяемый формат описания содержимого сборок. К тому же если это не слишком дорого, то можно определять собственные специальные “атрибуты”, которые легко включаются в метаданные типа. В мире управляемого кода почти любая сущность программы с типом может иметь присоединенные к ней метаданные, включая классы, методы, параметры, возвращаемые значения, сборки и т.д.

Специальные атрибуты можно определить, унаследовав их от класса System.Attribute, а затем легко ассоциировать экземпляр специального атрибута почти с любой сущностью в сборке.

С помощью метаданных можно получать доступ и исследовать определения типов и присоединенные к ним атрибуты.

Метаданные могут сообщить о том, поддерживает ли определенный класс объекта конкретный метод, прежде чем пытаться вызвать его, либо порожден ли данный класс от какого-то другого. Процесс просмотра метаданных называется рефлексией. Обычно рефлексия типов в сборке начинается с объекта System.Туре.

Получить один из этих экземпляров типов можно с помощью ключевого слова С# typeof, вызова System.Assembly.GetType () или нескольких других способов. В общем случае ключевое слово typeof более эффективно, потому что вычисляется во время компиляции, в то время как метод GetType (), хотя и является более гибким, поскольку ему можно передавать произвольную строку, запускается во время выполнения. После получения объекта типа можно определить, является ли он классом, интерфейсом, структурой и т.п., какие методы у него есть, а также количество и типы содержащихся в нем полей.

Чтобы пояснить, зачем нужны метаданные, следует отметить, что в технологии СОМ/ DCOM используются несколько другие приемы. Если вы когда-нибудь создавали компоненты СОМ, то должны быть знакомы с IDL (Interface Description Language — язык описания интерфейсов), который представляет собой независимый от платформы язык описания интерфейсов и компонентов.

Обычно вы предоставляете своему заказчику СОМ-компонент, упакованный в DLL-библиотеку или исполняемую программу, вместе с IDL-описанием. Это описание служит той же цели, что и заголовочный файл для библиотек С++ или документация, сопровождающая DLL-библиотеку.

Обычно IDL-описание прогоняется через компилятор IDL, который генерирует “родной” код для последующего с ним взаимодействия. Библиотека типов (Type Library — TLB) служит почти той же цели, что IDL, но имеет двоичный формат, который обычно потребляют высокоуровневые языки вроде Visual Basic. К сожалению, IDL и TLB не полностью перекрывают друг друга. Некоторые вещи могут быть описаны на IDL, но не в TLB, и наоборот.

Поскольку сборки являются самоописательными, единственное, что нужно компилятору С# для разрешения использования типов — это список сборок, на которые ссылается текущая, чтобы скомпилировать и построить программу. Имея такой список, для разрешения зависимостей компилятор может обращаться к метаданным, содержащимся внутри сборок. Это прекрасная система, и она исключает некоторые чреватые ошибками детали из процесса кодирования С#.

В управляемом мире вам больше не нужно заботиться о дополнительном багаже в виде заголовочных файлов или файлов IDL. Правда, нельзя утверждать, что больше не понадобится предоставлять и документацию, потому что документация полезна всегда. Но, имея сборку, вы получаете полноценно упакованную сущность, содержащую и код, и описания, необходимые для ее использования.

Если сборка состоит из единственного файла, как чаще всего и бывает, то этот файл содержит все необходимое для того, чтобы использовать код, находящийся в этой сборке.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100