field
: SomeAttr] // Применяется к полям, созданным компилятором
[
method
: SomeAttr] // Применяется к созданным
// компилятором методам add и remove
public event EventHandler SomeEvent;
}
Теперь, когда вы знаете, как применять настраиваемые атрибуты, давайте раз-
беремся, что они собой представляют. Настраиваемый атрибут — это всего лишь
467
Сфера.применения.настраиваемых.атрибутов
экземпляр типа. Для соответствия общеязыковой спецификации (CLS) он дол-
жен прямо или косвенно наследовать от абстрактного класса
System.Attribute
.
В C# допустимы только CLS-совместимые атрибуты. В документации на .NET
Framework SDK можно обнаружить определения следующих классов из предыду-
щего примера:
StructLayoutAttribute
,
MarshalAsAttribute
,
DllImportAttribute
,
InAttribute
и
OutAttribute
. Все они находятся в пространстве имен
System.
Runtime.InteropServices
, при этом классы атрибутов могут определяться в любом
пространстве имен. Можно заметить, что все перечисленные классы являются произ-
водными от класса
System.Attribute
, как и положено CLS-совместимым атрибутам.
ПриМеЧание
При.определении.атрибута.компилятор.позволяет.опускать.суффикс.Attribute,.что.
упрощает.ввод.кода.и.делает.его.более.читабельным .Я.активно.использую.эту.воз-
можность.в.приводимых.в.книге.примерах.—.например,.пишу.[DllImport( )].вместо.
[DllImportAttribute( )]
Как уже упоминалось, атрибуты являются экземплярами класса. И этот класс
должен иметь открытый конструктор для создания экземпляров. А значит, синтаксис
применения атрибутов аналогичен вызову конструктора. Кроме того, используемый
язык может поддерживать специальный синтаксис определения открытых полей
или свойств класса атрибутов. Рассмотрим это на примере. Вернемся к приложению,
в котором атрибут
DllImport
применяется к методу
GetVersionEx
:
[DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
Выглядит довольно странно, но вряд ли вы будете когда-нибудь использо-
вать подобный синтаксис для вызова конструктора. Согласно описанию класса
DllImportAttribute
в документации, его конструктор требует единственного па-
раметра типа
String
. В рассматриваемом примере в качестве параметра передается
строка
"Kernel32"
. Параметры конструктора называются
позиционными
(positional
parameters); при применении атрибута следует обязательно их указывать.
А что с еще двумя «параметрами»? Показанный особый синтаксис позволяет
задавать любые открытые поля или свойства объекта
DllImportAttribute
после его
создания. В рассматриваемом примере при создании этого объекта его конструк-
тору передается строка
"Kernel32"
, а открытым экземплярным полям
CharSet
и
SetLastError
присваиваются значения
CharSet.Auto
и
true
соответственно.
«Параметры», задающие поля или свойства, называются
именованными
(named
parameters); они являются необязательными. Чуть позже мы рассмотрим, как ини-
циировать конструирование экземпляра класса
DllImportAttribute
.
Следует заметить, что к одному элементу можно применить несколько атри-
бутов. Скажем, в приведенном в начале главы фрагменте кода к параметру
ver
метода
GetVersionEx
применяются атрибуты
In
и
Out
. Учтите, что порядок следо-
вания атрибутов в такой ситуации не имеет значения. В C# отдельные атрибуты
могут заключаться в квадратные скобки; также возможно перечисление наборов
468
Do'stlaringiz bilan baham: |