ВниМание
Настраиваемый.атрибут.лучше.всего.представлять.себе.как.экземпляр.класса,.се-
риализованный.в.байтовый.поток,.находящийся.в.метаданных .В.период.выполнения.
байты.из.метаданных.десериализуются.для.конструирования.экземпляра.класса
473
Выявление.настраиваемых.атрибутов
На.самом.деле.компилятор.генерирует.информацию,.необходимую.для.создания.
экземпляра.класса.атрибутов,.и.размещает.ее.в.метаданных .Каждый.параметр.кон-
структора.записывается.с.однобайтным.идентификатором,.за.которым.следует.его.
значение .Завершив.«сериализацию».параметров,.компилятор.генерирует.значения.
для.каждого.указанного.поля.и.свойства,.записывая.его.имя,.за.которым.следует.
однобайтный.идентификатор.типа.и.значение .Для.массивов.сначала.указывается.
количество.элементов
Выявление настраиваемых атрибутов
Само по себе определение атрибутов бесполезно. Вы можете определить любой
класс атрибута и применить его в произвольном месте, но это приведет только к по-
явлению в вашей сборке дополнительных метаданных, никак не влияя на работу
приложения.
Как показано в главе 15, применение к перечислимому типу
System.Enum
атрибута
Flags
меняет поведение его методов
ToString
и
Format
. Причиной это-
му является происходящая во время выполнения проверка, не связан ли атрибут
Flags
с перечислимым типом, с которым работают данные методы. Код может
анализироваться на наличие атрибутов при помощи технологии, называемой
от-
ражением
(reflection). Подробно она рассматривается в главе 23, здесь же я только
продемонстрирую ее применение.
Если бы вы были разработчиком из Microsoft, которому поручено реализовать
метод
Format
типа
Enum
, вы бы сделали это примерно так:
public override String ToString() {
// Применяется ли к перечислимому типу экземпляр типа FlagsAttribute?
if (this.GetType().IsDefined(typeof(FlagsAttribute), false)) {
// Да; выполняем код, интерпретирующий значение как
// перечислимый тип с битовыми флагами
...
} else {
// Нет; выполняем код, интерпретирующий значение как
// обычный перечислимый тип
...
}
...
}
Этот код обращается к методу
IsDefined
типа
Type
, заставляя систему по-
смотреть метаданные этого перечислимого типа и определить, связан ли с ним
экземпляр класса
FlagsAttribute
. Если метод
IsDefined
возвращает значение
true
, значит, экземпляр
FlagsAttribute
связан с перечислимым типом, и метод
Format
будет считать, что переданное значение содержит набор битовых флагов.
В противном случае переданное значение будет восприниматься как обычный
перечислимый тип.
474
Do'stlaringiz bilan baham: |