Поделиться через


Хранилище метаданных

Обновлен: Ноябрь 2007

Платформа Windows Presentation Foundation (WPF) для Visual Studio (конструктор) отделяет метаданные времени разработки от реализации. Отделение метаданных от кода среды выполнения важным принципом разработки по следующим причинам.

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

  • Включение метаданных в код среды выполнения не позволяет таким внешним инструментам, как WPF (конструктор) или Expression Blend изменять эти метаданные впоследствии. Это значительно затрудняет перенастройку. Без разделения кода и метаданных времени разработки Visual Studio не может изменять версию своих конструкторов без новой версии .NET Framework.

  • Включение метаданных в код среды выполнения существенно увеличивает размер сборки среды выполнения. Атрибуты времени разработки также замедляют работу среды выполнения. Загрузка дополнительных атрибутов в память влияет на такие характеристики среды выполнения, как привязка данных, использующая механизм отражения.

  • Метаданные времени разработки отвечают за "персонализацию" конструктора. Характеристики конструктора в основном зависят от главного приложения, а не от среды выполнения. Для формирования набора функций, предназначенного для пользователей определенного профиля, в WPF (конструктор) и средстве Expression Blend используются различные наборы метаданных. 

Хранилище метаданных

Хранилище метаданных является местом хранения метаданных времени разработки. API-интерфейс хранилища метаданных довольно прост. Добавление таблицы с атрибутами метаданных осуществляется путем вызова метода AddAttributeTable. После добавления таблицы в хранилище метаданных доступ к атрибутам, определенным в этой таблице, осуществляется с помощью запросов TypeDescriptor. Если тип уже был запрошен и таблица содержит дополнительные атрибуты для этого типа, то для сообщения об изменении метаданных этого типа создается событие Refreshed.

Таблица атрибутов

Таблица атрибутов, по сути, является словарем, предназначенным только для чтения, но ключи и значения в ней вычисляются раздельно. Таблицы атрибутов удобно использовать для запроса атрибутов определенного типа. Реальный набор атрибутов создается по требованию. Для извлечения специализированных метаданных определенного типа используется метод GetCustomAttributes.

В таблицах атрибутов поддерживаются только свойства типов. Атрибуты полей и методов в таблицах атрибутов не поддерживаются.

Конструктор таблиц атрибутов

Создание таблицы атрибутов начинается с создания экземпляра класса AttributeTableBuilder. Добавление метаданных в конструктор таблиц атрибутов производится путем вызова перегрузок методов AddCustomAttributes. После завершения добавления метаданных создание таблицы атрибутов в конструкторе таблиц атрибутов осуществляется путем вызова метода CreateTable. Методы конструктора таблиц атрибутов поддерживают делегаты обратного вызова, поэтому создание таблицы атрибутов может быть отложено до необходимости.

Создание настраиваемых атрибутов

Для хранилища метаданных предполагается, что у настраиваемых атрибутов правильно переопределено свойство TypeId. Хранилище метаданных использует свойство TypeId, чтобы определять, следует ли считать два атрибута одного или разных типов одним экземпляром.

Свойство TypeId определено в базовом классе Attribute следующим образом.

    public class Attribute
    {
        ...

        public virtual object TypeId
        {
            get
            {
                return base.GetType();
            }
        }

        ...
    }

При подобной реализации два экземпляра одного типа Attribute будут выглядеть, как один атрибут. Один из этих экземпляров будет проигнорирован реализацией по умолчанию TypeDescriptor. Если такое поведение настраиваемого атрибута нежелательно, как в случае с классом FeatureAttribute, то свойство TypeId настраиваемого атрибута следует переопределить так, чтобы оно возвращало уникальный объект для каждого экземпляра типа. Например, в классе FeatureAttribute свойство TypeId переопределено следующим образом:

public override object TypeId
{
    get { return this; }
}

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

Соглашение об именовании сборок метаданных

Код времени разработки развертывается в специальных сборках метаданных. Возможности времени разработки, поддерживающиеся всеми конструкторами, развертываются в сборке с именем главной библиотеки с добавлением ".Design". Возможности времени разработки, поддерживающиеся только Visual Studio, развертываются в сборке с именем главной библиотеки с добавлением ".VisualStudio.Design". В следующей таблице показаны примеры имен для библиотеки элементов управления среды выполнения с именем CustomControlLibrary.dll. 

Конструктор

Имя сборки времени разработки

Только Visual Studio

CustomControlLibrary.VisualStudio.Design.dll

Только Expression Blend

CustomControlLibrary.Expression.Design.dll

Все конструкторы

CustomControlLibrary.Design.dll

Загрузка сборок метаданных

Когда конструктор загружает сборку среды выполнения, он также выполняет поиск соответствующих сборок метаданных. Если соответствующие сборки метаданных найдены, то они загружаются сразу после того, как будет загружена сборка исполняющей среды.

При добавлении ссылки на новую сборку в проект выполняется поиск и загрузка всех соответствующих сборок метаданных.

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

Bb546923.alert_note(ru-ru,VS.90).gifПримечание.

Сборки метаданных *.Design.dll загружаются перед сборками *.VisualStudio.Design.dll и *.Expression.Design.dll, определяемыми конструктором. Метаданные, определяемые конструктором, заменяют общие метаданные.

Порядок поиска сборок метаданных

К сборкам, ссылки на которые есть в проекте, применяется следующий порядок поиска.

  1. Конструктор выполняет поиск в папке, где находится сборка среды выполнения, на которую есть ссылка. Для поиска этого расположения используется тот же алгоритм, который используется при построении для поиска сборок, включающий поиск в папках SDK и дополнительных расположениях.

  2. Конструктор выполняет поиск вложенной папки "Конструктор" в папке, где расположена сборка среды выполнения элемента управления.

Хотя сборка исполняющей среды элемента управления может быть выгружена из глобального кэша сборок (GAC), ссылка всегда указывает на расположение вне GAC. Часто это расположение находится в папке SDK. В WPF (конструктор) для поиска сборки, на которую имеется ссылка, в файловой системе используются API-интерфейсы Visual Studio даже в случае, когда не указано свойство проекта HintPath. Конструктор пытается загрузить сборку метаданных не из расположения, откуда загружается сборка среды выполнения элемента управления, а из расположения, на которое ссылается сборка среды выполнения элемента управления.

Косвенно указанные сборки загружаются, поскольку на них ссылается сборка, на которую ссылается проект. Например, если имеется проект со ссылкой на сборку MyAssembly, а в сборке MyAssembly присутствует ссылка на сборку MyOtherAssembly, на которую нет непосредственных ссылок в данном проекте, сборка MyOtherAssembly считается косвенно указанной сборкой.

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

Сборка, на которую есть ссылка

Процедура поиска

Файл, загруженный из GAC

Выполняется поиск соответствующей сборки метаданных в папках SDK. Если эта сборка найдена, то для поиска всех соответствующих сборок метаданных используется путь к ней и вложенная папка Design.

Файл загруженный из расположения, находящегося вне GAC

Выполняется поиск соответствующих сборок метаданных в папке сборки среды выполнения и ее вложенной папке Design.

Поиск реализации IRegisterMetadata

Сборки метаданных должны содержать одну или несколько реализаций интерфейса IRegisterMetadata. Реализация IRegisterMetadata находится с помощью отражения. Если в сборке существует несколько реализаций IRegisterMetadata, то каждая реализация создается и вызывается в порядке, возвращенном интерфейсом API Reflection.

См. также

Ссылки

Microsoft.Windows.Design.Metadata

MetadataStore

AttributeTable

AttributeTableBuilder

FeatureAttribute

Другие ресурсы

Расширяемость среды конструктора WPF