Сокращенное именование атрибутов

На самом деле по соглашению атрибуты имеют суффикс Attribute, но его можно опускать при использовании в коде. Поэтому в действительности класс, реализующий атрибут [NonSerialized], имеет имя NonSerializedAttribute, и равноценными будут записи

[NonSerialized]

uint _color;

и

[NonSerializedAttribute]

uint _color;

Создание собственных атрибутов:

Пример:

class ShapeDescriptionAttribute: System.Attribute

{

// свойство

public string Description { get; set; }

// конструкторы

public ShapeDescriptionAttribute() { }

public ShapeDescriptionAttribute(string description)

{

Description = description;

}

}

Как видно, атрибут – обычный класс, только унаследованный от System.Attribute.

Применение собственных атрибутов:

Пример:

[ShapeDescription("Точка на плоскости")]

class Point: Shape

{

double _x;

double _y;

};

[ShapeDescription(Description = "Окружность на плоскости")]

class Circle: Shape

{

Point _center;

double _radius;

}

В первом случае используется инициализация через конструктор атрибута, во втором —так называемый синтаксис именованных атрибутов. Для него нужно, чтобы в классе атрибута были доступные для записи свойства (как, например Description).

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

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

public enum AttributeTargets

{

All, Assembly, Class, Constructor, Delegate, Enum, Event,

Field, GenericParameter, Interface, Method, Module, Parameter,

Property, ReturnValue, Struct

}

Атрибут [AttributeUsage] также позволяет устанавливать свойство AllowMultiple, которое указывает, может ли атрибут применяться к одному и тому же элементу более одного раза (по умолчанию false). Помимо этого он также позволяет указывать, должен ли атрибут наследоваться производными классами, за счет применения именованного свойства Inherited (по умолчанию true). Например:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,

Inherited = false)]

class ShapeDescriptionAttribute: System.Attribute

{

...

};

Атрибуты уровня сборки и модуля:

Атрибуты можно также применять ко всем типам внутри конкретного модуля (если речь идет о многофайловой сборке) или ко всем модулям внутри отдельной сборки, используя, соответственно, дескрипторы [module:] и [assembly:]. Например

[ assembly: Serializable]

Применяет атрибут [Serializable] ко всем элементам в сборке.

Рефлексия атрибутов:

// Получение типа, представляющего Circle

Type t = typeof (Circle);

// Получение всех атрибутов Circle

object [] customAtts = t.GetCustomAttributes(false);

// Вывод описания

foreach (ShapeDescriptionAttribute a in customAtts)

Console.WriteLine("{0}", a.Description);

Выводы:

· Применение атрибутов приводит к включению в сборку дополнительных метаданных.

· Атрибуты, по сути, остаются бесполезными до тех пор, пока какой-то другой агент не воспроизведет их через рефлексию.

· В С# атрибуты указываются в квадратных скобках.

· Атрибуты в.NET представляют собой классы, унаследованные от класса System.Attribute

· Можно ограничивать область использования атрибутов, при помощи элементов перечисления AttributeTargets

· Рефлексия атрибутов осуществляется при помощи метода Type.GetCustomAttributes()





double arrow
Сейчас читают про: