Поиск

Определение целевого типа атрибута

А сейчас снова взгляните на атрибут AttributeUsage из предыдущего раздела. Заметьте: параметр validon является позиционным и, естественно, обязательным. Он позволяет задавать типы, к которым может быть прикреплен атрибут. На самом деле тип параметра validon атрибута Attribute-Usage — AttributeTargets, представляющий собой перечисление, определяемое так:

public enum AttributeTargets <
Assembly = 0x0001,
Module = 0x0002,
Class = 0x0004,
Struct = 0x0008,
Enum = 0x0010,
Constructor = 0x0020,
Method = 0x0040,
Property = 0x0080,
Field = 0x0100,
Event = 0x0200,
Interface = 0x0400,
Parameter = 0x0800,
Delegate = 0x1000,
All = Assembly | Module | Class | Struct | Enum |
Constructor | Method | Property | Field | Event |
Interface | Parameter | Delegate,
ClassMembers = Class | Struct | Enum | Constructor
| Method | Property | Field | Event | Delegate | Interface, }

При использовании атрибута Attribute Usage можно задать Attribute-Targets.All. Это позволяет прикрепить атрибут к любому из типов в списке перечисления AttributeTargets. Если вы вообще не определили Attribute-Usage, можете прикрепить атрибут к любому типу — это значение по умолчанию. И тут вы можете спросить: "А зачем вообще значение vali-don?" А затем, что с вашим атрибутом могут применяться именованные параметры, которые вы, может быть, захотите изменить. Помните: используя именованный параметр, вы должны поставить все позиционные параметры перед ним. Это позволяет легко задавать применение атрибутов по умолчанию, определяемое AttriubuteTargets.All, и при этом устанавливать именованные параметры.

Итак, когда и для чего задавать параметр validon (AttributeTargets)! Когда вам нужно точно контролировать способы применения атрибута. В наших примерах мы создали атрибут RemoteObjeci'Attribute, применимый только к классам, атрибут TransactionableAttribute, применимый только к методам, и атрибут Registry Key Attribute, который имеет смысл лишь по отношению к полям. Если мы хотим убедиться, что они были использованы для аннотации только тех типов, для которых они разработаны, мы можем определить их так (для ясности тела атрибутов не приводятся):

[Att ributeUsage(Att ributeTa rgets.Class)]
public class RemoteObjectAttribute : Attribute] {
}
[Att rlbuteUsage(AttributeTargets.Method)]
public class TransactionableAttribute : Attribute
{
}
[Att ributeUsage(Att ributeTargets.Field)]
public class RegistryKeyAttribute : Attribute
<
}

И последний момент относительно перечисления AttributeTargets: вы можете комбинировать члены с помощью оператора |. Если у вас есть атрибут, применимый и к полям, и к свойствам, Attribute Usage можно прикрепить так:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]