Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Троелсен Э. Язык программирования С# 2010 и п...docx
Скачиваний:
113
Добавлен:
21.09.2019
Размер:
6.92 Mб
Скачать

Применение пользовательских атрибутов

После получения VehicleDescriptionAttribute из System.Attribute вы можете снабжать свои транспортные средства такими аннотациями, какими пожелаете.

// Назначение описания с помощью 'именованного свойства'.

[Serializable,

VehicleDescription(Description = "Мой сияющий Харлей")]

public class Motorcycle {

 //…

}

[SerializableAttribute]

[ObsoleteAttribute("Класс устарел, используйте другой транспорт!"), VehicleDescription("Старая серая кляча, она уже совсем не та…")]

public class HorseAndBuggy {

 //…

}

[VehicleDescription("Большое, тяжелое, но высокотехнологичное авто"

public class Winnebago {

 //…

}

Обратите внимание на то, что описание класса Motorcycle здесь указано с помощью нового элемента синтаксиса, называемого именованным свойством. В конструкторе первого атрибута [VehicleDescription] соответствующее значение System.String устанавливается с помощью пары "имя-значение". При отображении этого атрибута внешним агентом соответствующее значение передается свойству Description (синтаксис именованного свойства здесь корректен только в том случае, когда атрибут предлагает перезаписываемое свойство .NET). В противоположность этому типы HorseAndBuggy и Winnebago не используют синтаксис именованного свойства, а просто передают строковые данные в пользовательский конструктор.

После компиляции компоновочного блока AttributedCarLibrary можно использовать ildasm.exe, чтобы увидеть метаданные с описанием добавленного типа. Так, на рис. 12.8 показано встроенное описание типа Winnebago.

Рис. 12.8. Встроенные данные описания транспортного средства

Ограничение использования атрибута

По умолчанию пользовательские атрибуты могут применяться к любой части программного кода (к методам, классам, свойствам и т.д.). Поэтому, если только это имеет смысл, можно использовать VehicleDescription для определения (среди прочего) методов, свойств или полей.

[VehicleDescription("Большое, тяжелое, но высокотехнологичное авто")]

public class Winnebago {

 [VehicleDescription("Мой мощный CD-плейер")]

 public void PlayMusic(bool On) {

  …

 }

}

В некоторых случаях это оказывается именно тем, что нужно. Но в других случаях бывает нужно создать пользовательский атрибут, который должен применяться только к определенным элементам программного кода. Если вы хотите ограничить контекст применения пользовательского атрибута, то при определении пользовательского атрибута нужна применить атрибут [AttributeUsage]. Атрибут [AttributeUsage] позволяет указать любую комбинацию значений (связанных операцией OR) из перечня AttributeTargets.

// Этот перечень задает возможные целевые значения для атрибута.

public enum AttributeTargets {

 All, Assembly, Class, Constructor,

 Delegate, Enum, Event, Field,

 Interface, Method, Module, Parameter,

 Property, ReturnValue, Struct

}

Кроме того, [AttributeUsage] позволяет опционально установить именованное свойство (AllowMultiple), которое указывает, может ли атрибут примениться к одному и тому же элементу многократно. Точно так же с помощью именованного свойства Inherited атрибут [AttributeUsage] позволяет указать, должен ли создаваемый атрибут наследоваться производными классами.

Чтобы атрибут [VehicleDescription] мог применяться к классу или структуре только один раз (и соответствующее значение не наследовалось производными типами), можно изменить определение VehicleDescriptionAttribute так.

// На этот раз для аннотации нашего пользовательского атрибута

// мы используем атрибут AttributeUsage.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.StructAllowMultiple = false, Inherited = false)]

public class VehicleDescriptionAttribute: System.Attribute {

 …

}

Теперь если разработчик попытается применить атрибут [VehicleDescription] к чему-либо, кроме класса или структуры, будет сгенерировано сообщение об ошибке компиляции.

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