Чтение онлайн

на главную

Жанры

Полное руководство. С# 4.0
Шрифт:

Эта последовательность кода оказывается вполне работоспособной, поскольку класс MemberInfo является базовым для класса Туре. Следовательно, t — это экземпляр объекта класса MemberInfo.

Имея ссылку на атрибут, можно получить доступ к его членам. Благодаря этому ин формация об атрибуте становится доступной для программы, использующей элемент, к которому присоединен атрибут. Например, в следующей строке кода выводится со держимое свойства Remark. Console.WriteLine(rа.Remark);

Ниже приведена программа, в которой все изложенные выше особенности приме нения атрибутов демонстрируются на примере атрибута RemarkAttribute. // Простой пример применения атрибута. using System; using System.Reflection; [AttributeUsage(AttributeTargets.All)] public class RemarkAttribute : Attribute { string pri_remark; // базовое поле свойства Remark public RemarkAttribute(string comment) { pri_remark = comment; } public string Remark { get { return pri_remark; } } } [RemarkAttribute("В

этом классе используется атрибут.")] class UseAttrib { // ... } class AttribDemo { static void Main { Type t = typeof(UseAttrib); Console.Write("Атрибуты в классе " + t.Name + ": "); object[] attribs = t.GetCustomAttributes(false); foreach(object о in attribs) { Console.WriteLine(o); } Console.Write("Примечание: "); // Извлечь атрибут RemarkAttribute. Type tRemAtt = typeof(RemarkAttribute); RemarkAttribute ra = (RemarkAttribute) Attribute.GetCustomAttribute(t, tRemAtt); Console.WriteLine(ra.Remark); } }

Эта программа дает следующий результат. Атрибуты в классе UseAttrib: RemarkAttribute Примечание: В этом классе используется атрибут. Сравнение позиционных и именованных параметров

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

Но для атрибута доступны также именованные параметры, которым можно при сваивать первоначальные значения по их именам. В этом случае значение имеет имя, а не позиция параметра.

ПРИМЕЧАНИЕ Несмотря на то что именованные параметры атрибутов, по существу, подобны именован ным аргументам методов, они все же отличаются в деталях.

Именованный параметр поддерживается открытым полем или свойством, которое должно быть нестатическим и доступным только для записи. Любое поле или свой ство подобного рода может автоматически использоваться в качестве именованного параметра. Значение присваивается именованному параметру с помощью соответ ствующего оператора, расположенного в списке аргументов при вызове конструктора атрибута. Ниже приведена общая форма объявления атрибута, включая именованные параметры. [attrib(список_позиционных_параметров, именованный_параметр_1 = значение, именованный_параметр_2 = значение, ...)]

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

Применение именованного параметра лучше всего показать на конкретном при мере. Ниже приведен вариант класса RemarkAttribute, в который добавлено поле Supplement, предназначенное для хранения дополнительного примечания. [AttributeUsage(AttributeTargets.All)] public class RemarkAttribute : Attribute { string pri remark; // базовое поле свойства Remark // Это поле можно использовать в качестве именованного параметра. public string Supplement; public RemarkAttribute(string comment) { pri_remark = comment; Supplement = "Отсутствует"; } public string Remark { get { return pri_remark; } } }

Как видите, поле Supplement инициализируется в конструкторе символьной стро кой "Отсутствует". Другого способа присвоить ему первоначальное значение в кон структоре не существует. Но поскольку поле Supplement является открытым в классе RemarkAttribute, его можно использовать в качестве именованного параметра, как показано ниже. [RemarkAttribute("В этом классе используется атрибут.", Supplement = "Это дополнительная информация.")] class UseAttrib { // ... }

Обратите особое внимание на вызов конструктора класса RemarkAttribute. В этом конструкторе первым, как и прежде, указывается позиционный параметр, а за ним через запятую следует именованный параметр Supplement, которому присваивается конкретное значение. И наконец, закрывающая скобка, ), завершает вызов конструкто ра. Таким образом, именованный параметр инициализируется в вызове конструктора. Этот синтаксис можно обобщить: позиционные параметры должны указываться в том порядке, в каком они определены в конструкторе, а именованные параметры — в про извольном порядке и вместе с присваиваемыми им значениями.

Ниже приведена программа, в которой демонстрируется применение поля Supplement в качестве именованного параметра атрибута. // Использовать именованный параметр атрибута. using System; using System.Reflection; [AttributeUsage(AttributeTargets.All)] public class RemarkAttribute : Attribute { string pri_remark; // базовое поле свойства Remark public string Supplement; // это именованный параметр public RemarkAttribute(string comment) { pri_remark = comment; Supplement = "Отсутствует"; } public string Remark { get { return pri_remark; } } } [RemarkAttribute("В этом классе используется атрибут.", Supplement = "Это дополнительная информация.")] class UseAttrib { // ... } class NamedParamDemo { static void Main { Type t = typeof(UseAttrib); Console.Write("Атрибуты в классе " + t.Name + "); object[] attribs = t.GetCustomAttributes(false); foreach(object о in attribs) { Console.WriteLine(o); } // Извлечь атрибут RemarkAttribute. Type tRemAtt = typeof(RemarkAttribute); RemarkAttrib.ute ra = (RemarkAttribute) Attribute.GetCustomAttribute(t, tRemAtt); Console.Write("Примечание: "); Console.WriteLine(ra.Remark); Console.Write("Дополнение: ") ; Console.WriteLine(ra.Supplement); } }

При выполнении этой программы получается следующий результат. Атрибуты в классе UseAttrib: RemarkAttribute Примечание: В этом классе используется атрибут. Дополнение: Это дополнительная информация.

Прежде чем перейти к следующему вопросу, следует особо подчеркнуть, что поле pri_remark нельзя использовать в качестве именованного параметра, поскольку оно закрыто в классе RemarkAttribute. Свойство Remark также нельзя использовать в ка честве именованного параметра, потому что оно доступно только для чтения. Напом ним, что в качестве именованных параметров могут служить только открытые поля и свойства.

Открытое и доступное только для чтения свойство может использоваться в качестве именованного параметра таким же образом, как и открытое поле. В качестве примера ниже показано, как автоматически реализуемое свойство Priority типа int вводится в класс RemarkAttribute. // Использовать свойство в качестве именованного параметра атрибута. using System; using System.Reflection; [AttributeUsage(AttributeTargets.All)] public class RemarkAttribute : Attribute { string pri_remark; // базовое поле свойства Remark public string Supplement; // это именованный параметр public RemarkAttribute(string comment) { pri_remark = comment; Supplement = "Отсутствует"; Priority = 1; } public string Remark { get { return pri_remark; } } // Использовать свойство в качестве именованного параметра. public int Priority { get; set; } } [RemarkAttribute("В этом классе используется атрибут.", Supplement = " Это дополнительная информация.", Priority = 10)] class UseAttrib { // ... } class NamedParamDemo { static void Main { Type t = typeof(UseAttrib); Console.Write("Атрибуты в классе " + t.Name + "); object[] attribs = t.GetCustomAttributes(false); foreach(object о in attribs) { Console.WriteLine(o); } // Извлечь атрибут RemarkAttribute. Type tRemAtt = typeof(RemarkAttribute); RemarkAttribute ra = (RemarkAttribute) Attribute.GetCustomAttribute(t, tRemAtt); Console.Write("Примечание: "); Console.WriteLine(ra.Remark); Console.Write("Дополнение: "); Console.WriteLine(ra.Supplement); Console.WriteLine("Приоритет: " + ra.Priority); } }

Вот к какому результату приводит выполнение этого кода. Атрибуты в классе UseAttrib: RemarkAttribute Примечание: В этом классе используется атрибут. Дополнение: Это дополнительная информация. Приоритет: 10

В данном примере обращает на себя внимание порядок указания атрибутов перед классом UseAttrib, как показано ниже. [RemarkAttribute("В этом классе используется атрибут.", Supplement = " Это дополнительная информация.", Priority = 10)] class UseAttrib { // ... }

Именованные параметры атрибутов Supplement и Priority не обязательно ука зывать в каком-то определенном порядке. Порядок их указания можно свободно из менить, не меняя сами атрибуты.

И последнее замечание: тип параметра атрибута (как позиционного, так и имено ванного) должен быть одним из встроенных простых типов, object, Туре, перечисле нием или одномерным массивом одного из этих типов. Встроенные атрибуты

В C# предусмотрено несколько встроенных атрибутов, но три из них имеют осо бое значение, поскольку они применяются в самых разных ситуациях. Это атрибуты AttributeUsage, Conditional и Obsolete, рассматриваемые далее по порядку. Атрибут AttributeUsage

Поделиться:
Популярные книги

Горькие ягодки

Вайз Мариэлла
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Горькие ягодки

Кодекс Охотника. Книга XXVI

Винокуров Юрий
26. Кодекс Охотника
Фантастика:
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXVI

Девяностые приближаются

Иванов Дмитрий
3. Девяностые
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Девяностые приближаются

Эффект Фостера

Аллен Селина
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Эффект Фостера

Леди Малиновой пустоши

Шах Ольга
Любовные романы:
любовно-фантастические романы
6.20
рейтинг книги
Леди Малиновой пустоши

Убийца

Бубела Олег Николаевич
3. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Убийца

Попутчики

Страйк Кира
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Попутчики

Последняя Арена 11

Греков Сергей
11. Последняя Арена
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Последняя Арена 11

На границе империй. Том 9. Часть 5

INDIGO
18. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 5

Последний Паладин. Том 6

Саваровский Роман
6. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 6

Измена. Не прощу

Леманн Анастасия
1. Измены
Любовные романы:
современные любовные романы
4.00
рейтинг книги
Измена. Не прощу

Польская партия

Ланцов Михаил Алексеевич
3. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Польская партия

Ох уж этот Мин Джин Хо – 3

Кронос Александр
3. Мин Джин Хо
Фантастика:
попаданцы
5.00
рейтинг книги
Ох уж этот Мин Джин Хо – 3

Третий. Том 2

INDIGO
2. Отпуск
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 2