где элемент обозначает объект класса MemberInfo, описывающий тот элемент, для ко торого создаются атрибуты, тогда как тип_атрибута — требуемый атрибут. Данный метод используется в том случае, если имя получаемого атрибута известно заранее, что зачастую и бывает. Так, если в классе UseAttrib имеется атрибут RemarkAttribute, то для получения ссылки на этот атрибут можно воспользоваться следующей после довательностью кода. // Получить экземпляр объекта класса MemberInfо, связанного // с классом, содержащим атрибут RemarkAttribute. Type t = typeof(UseAttrib); // Извлечь атрибут RemarkAttribute. Type tRemAtt = typeof(RemarkAttribute); RemarkAttribute ra = (RemarkAttribute) Attribute.GetCustomAttribute(t, tRemAtt);
Эта последовательность кода оказывается вполне работоспособной, поскольку класс 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; } } }