public bool IsError { get; }
public string Message { get; }
public ObsoleteAttribute(string message, bool error);
public ObsoleteAttribute(string message);
public ObsoleteAttribute();
}
Когда вы указываете параметры конструктора для атрибута, атрибут не размещается в памяти до тех пор, пока эти параметры не отобразятся другим типом или внешним программным средством. Строки, определенные на уровне атрибута, просто запоминаются в компоновочном блоке, как часть метаданных.
Атрибут Obsolete в действии
Теперь, когда класс HorseAndBuggy обозначен как устаревший, при размещении экземпляра этого типа вы должны увидеть соответствующую строку в сообщении, появившемся в окне со списком ошибок Visual Studio 2005 (рис. 12.7).
Рис. 12.7. Атрибуты в действии
В данном случае "другим фрагментом программного обеспечения", отображающим атрибут [Obsolete], является компилятор C#.
Сокращенное представление атрибутов в C#
При внимательном изучении материала этой главы вы могли заметить, что фактическим именем класса атрибута [Obsolete] является не Obsolete, a ObsoleteAttribute. По соглашению для имен все атрибуты .NET (и пользовательские атрибуты в том числе) должны в конце имени получить суффикс Attribute. Однако, чтобы упростить процедуру применения атрибутов, в языке C# не требуется, чтобы вы обязательно добавляли этот суффикс. Поэтому следующий вариант определения типа HorseAndBuggy будет идентичен предыдущему (при этом только потребуется ввести немного больше символов).
[SerializableAttribute]
[ObsoleteAttribute("Класс устарел, используйте другой транспорт!")]
public class HorseAndBuggy {
//…
}
Это упрощение предлагается самим языком C#, и следует подчеркнуть, что эту особенность поддерживают не все языки .NET. Так или иначе, к этому моменту нашего обсуждения вы должны понимать следующие основные особенности, касающиеся атрибутов .NET.
• Атрибуты являются классами, производными от System.Attribute.
• Информация атрибутов добавляется в метаданные.
• Атрибуты будут бесполезны до тех пор, пока другой агент не отобразит их.
• Атрибуты в C# применяются с использованием квадратных скобок.
Теперь мы рассмотрим то, как можно строить свои собственные пользовательские атрибуты и пользовательские программы, отображающие встроенные метаданные.
Создание пользовательских атрибутов
Первым шагом процесса построения пользовательского атрибута является создание нового класса, производного от System.Attribute. В продолжение автомобильной темы, используемой в этой книге, мы создадим новую библиотеку классов C# с именем AttributedCarLibrary. Соответствующий компоновочный блок определит группу транспортных средств (определения некоторых из них, мы уже увидели выше), и при их описании будет использован пользовательский атрибут VehiсleDescriptionAttribute,
// Пользовательский атрибут.
public sealed class VehicleDescriptionAttribute: System.Attribute {
private string msgData;
public VehicleDescriptionAttribute(string description) { msgData = description; }
public VehicleDescriptionAttribute() {}
public string Description {
get { return msgData; }
set { msgData = value; }
}
}
Как видите, VehicleDescriptionAttribute поддерживает приватную внутреннюю строку (msgData), значение которой можно установить с помощью пользовательского конструктора, а изменять - с помощью свойства типа (Description). Кроме того, что этот класс является производным от System.Attribute, его определение ничем особенным больше не отличается,
Замечание.С точки зрения безопасности рекомендуется, чтобы все пользовательские атрибуты…NET создавались, как изолированные классы.
Применение пользовательских атрибутов
После получения VehicleDescriptionAttribute из System.Attribute вы можете снабжать свои транспортные средства такими аннотациями, какими пожелаете.
// Назначение описания с помощью 'именованного свойства'.
[Serializable,
VehicleDescription(Description = "Мой сияющий Харлей")]
public class Motorcycle {
//…
}
[SerializableAttribute]
[ObsoleteAttribute("Класс устарел, используйте другой транспорт!"), VehicleDescription("Старая серая кляча, она уже совсем не та…")]
public class HorseAndBuggy {
//…
}
[VehicleDescription("Большое, тяжелое, но высокотехнологичное авто"
public class Winnebago {
//…
}
Читать дальше