Общие сведения о дескрипторах типов

Архитектура TypeDescriptor расширяет возможности отражения .NET.

Архитектура дескрипторов типов

Архитектура TypeDescriptor основана на базовом модуле отражения и добавляет к нему дополнительные правила и функции. Например, класс TypeDescriptor поддерживает объединение свойств-расширителей интерфейса IContainer, а также поддерживает фильтрацию свойств и событий с помощью интерфейса IDesigner.

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

Возможность

Описание

Подстановка экземпляров

Позволяет создавать произвольный тип при запросе другого типа.

Подстановка метаданных

Позволяет модифицировать метаданные объекта.

Перенаправление атрибутов

Обеспечивает возможность динамического задания атрибутов.

Целевая подстановка и затенение

Обеспечивает возможность использования одного объекта вместо другого.

Поддержка расширенных дескрипторов типов

Эта возможность обеспечивает доступ к свойствам объекта, добавленным другими объектами.

В целях реализации поддержки вышеперечисленных возможностей класс TypeDescriptor тесно интегрируется с различными функциями компонентной модели платформы .NET Framework. Он совместим с объектами COM, поставщиками расширений, конструкторами и свойствами среды CLR.

Примечание

Архитектура TypeDescriptor может использоваться как в коде времени выполнения, так и в коде времени конструирования.

Для обеспечения поддержки расширяемости классу TypeDescriptor сопутствует класс TypeDescriptionProvider и атрибут TypeDescriptionProviderAttribute. Для реализации совершенно отличного способа предоставления метаданных, соответствующего задачам разработчика, можно применить к классу атрибут TypeDescriptionProviderAttribute.

Класс TypeDescriptionProvider

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

Атрибут TypeDescriptionProvider

TypeDescriptionProviderAttribute — это атрибут, применимый к классам. Данный атрибут используется для указания наличия у типа пользовательского поставщика описания типа. В свою очередь, атрибут реализует возможность установки поставщика описания типа с помощью метаданных. Когда этот тип передается в любой интерфейс API класса TypeDescriptor, класс TypeDescriptor находит данный атрибут, создает экземпляр указанного с его помощью поставщика описания типа и вносит этот поставщик во внутренние таблицы TypeDescriptor. После этого TypeDescriptor продолжает обработку API. Обработка позволяет типу автоматически осуществить установку пользовательского поставщика описания типа по запросу.

Возможности дескрипторов типов

Архитектура TypeDescriptor реализует ряд возможностей, выходящих за рамки реализации, предоставляемой отражением платформы .NET Framework.

Подстановка экземпляров

Подстановка экземпляров происходит тогда, когда необходимо создать некий тип, но тип, который создается на самом деле, отличен от того, который требовалось создать. Подстановка экземпляров реализуется при замене всех вызовов оператора new на вызовы метода CreateInstance. Этот метод ищет во внутренних таблицах TypeDescriptor объект TypeDescriptionProvider, связанный с указанным типом данных. Если объект найден, то вызов делегируется ему.

Подстановка метаданных

Подстановка метаданных выполняется тогда, когда необходимо модифицировать метаданные одного или нескольких объектов. Типичное применение подстановки метаданных — реализация конструкторов. Для выполнения подстановки метаданных используются поставщики описаний типов, которые могут добавляться и удаляться с помощью следующих методов класса TypeDescriptor:

Перенаправление атрибутов

В объектной модели платформы .NET Framework существует несколько ситуаций, в которых тип свойства намеренно не конкретизируется. Например, свойство DataSource в классе DataGridView определяется как object. Подобная реализация позволяет источнику данных принимать ввод нескольких видов, но при этом отсутствует возможность для добавления метаданных, описывающих характеристики свойства. Для каждого свойства источника данных в платформе .NET Framework должны использоваться идентичные метаданные для преобразователей типов и редакторов типов в пользовательском интерфейсе.

В данной ситуации используется класс AttributeProviderAttribute. При задании этого атрибута для свойства правила получения атрибутов для коллекции Attributes дескриптора свойства изменяются. Обычно дескриптор свойства собирает локальные атрибуты, а затем объединяет их с атрибутами типа свойства. После применения атрибута AttributeProviderAttribute атрибуты извлекаются из типа, возвращаемого атрибутом AttributeProviderAttribute, а не из фактического типа свойства. Атрибут AttributeProviderAttribute применяется к источникам данных для указания IListSource в качестве конкретного типа источника данных; при этом для обеспечения возможности привязки данных к IListSource добавляются соответствующие метаданные. Подобное перенаправление позволяет внешним программам, например, Visual Studio, легко добавлять метаданные ко всем источникам данных.

Атрибуты, получаемые из типа, объявленного в атрибуте AttributeProviderAttribute, имеют приоритет над прочими атрибутами типа свойства и атрибутами свойства. Полный набор атрибутов, доступных в модуле слияния, приведен в следующем списке, упорядоченном по приоритету:

  1. атрибуты свойства;

  2. атрибуты поставщика атрибутов;

  3. атрибуты типа свойства.

Целевая подстановка и затенение

При целевой подстановке один объект заменяет другой. Типичное применение целевой подстановки — реализация конструкторов.

В архитектуре конструкторов платформы .NET Framework с компонентом может быть связан конструктор. Этот конструктор может реализовывать интерфейс IDesignerFilter и предоставлять собственные свойства. Эти свойства добавляются в набор свойств компонента, которому сопоставлен конструктор. Эти свойства могут быть новыми для компонента. Они также могут иметь то же имя и тип, что и свойства, уже определенные для компонента. Ситуация, в которой имя и тип нового свойства совпадают с аналогичными параметрами старого свойства, называется затенением, поскольку конструктор скрывает, или затеняет, существующее свойство компонента. На следующей иллюстрации показан пример затенения свойства.

Затемнение свойства Text

В данном примере и компонент и конструктор имеют по два свойства. Свойство Text затеняется, так как оно имеется и у конструктора, и у компонента. Конечным результатом вызова GetProperties будут три свойства. Одно из них присутствует в компоненте, а два других — в конструкторе.

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

    gridProp.SetValue(component, value);

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

Класс TypeDescriptor содержит встроенную логику обработки данной ситуации. При вызове свойства класс TypeDescriptor проверяет, относится ли переданный объект к типу члена. Если это так, то вызов продолжает выполнение. В противном случае класс пытается найти конструктор объекта; если конструктор найден и имеет правильный тип, класс заменяет экземпляр компонента экземпляром конструктора.

Целевую подстановку поддерживают следующие методы TypeDescriptor:

Поддержка расширенных дескрипторов типов

Метод GetExtendedTypeDescriptor возвращает расширенный дескриптор типа для переданного объекта. Расширенный дескриптор типа — это пользовательский дескриптор типа, предоставляющий свойства, которые добавлены к этому объекту другими объектами, а не определены для него фактически. Например, в компонентной модели платформы .NET Framework объекты, реализующие интерфейс IExtenderProvider, могут присоединять свойства к другим объектам, находящимся в том же контейнере IContainer. Метод GetTypeDescriptor не возвращает дескриптор типа, предоставляющий дополнительные расширенные свойства, однако метод GetExtendedTypeDescriptor возвращает набор этих расширенных свойств. Класс TypeDescriptor автоматически объединяет результаты обеих коллекций свойств.

Примечание

Хотя компонентная модель платформы .NET Framework поддерживает только расширенные свойства, метод GetExtendedTypeDescriptor также можно использовать для расширенных атрибутов и событий, если это поддерживает поставщик описания типа.

См. также

Ссылки

TypeDescriptor

TypeDescriptionProvider

TypeDescriptionProviderAttribute

ICustomTypeDescriptor

CustomTypeDescriptor

IContainer

IDesigner

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

Расширение поддержки времени разработки