Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Атрибуты






Платформа.NET позволяет расширять метаданные типов и сборок, используя систему атрибутов. Каждый атрибут (attribute) описывает дополнительную информацию, сохраняемую в метаданных для цели атрибута (attribute target) – сборки, модуля, типа, элементов типа, параметров метода. С точки зрения программиста атрибуту соответствует класса атрибута – это класс, наследуемый от System.Attribute.

Рассмотрим основные аспекты работы с атрибутами. Для создания атрибута нужно написать класс, удовлетворяющий перечисленным ниже требованиям:

1. Класс должен прямо или косвенно наследоваться от класса Attribute.

2. Тип открытых полей, свойств и параметров конструктора класса ограничен следующим набором: числовые типы (кроме decimal), bool, char, string, object, System.Type, перечисления; одномерные массивы указанных типов.

3. Имя класса должно заканчиваться суффиксом Attribute (это необязательное требование).

Приведём пример класса атрибута:

public class AuthorAttribute: Attribute

{

public string Name { get; private set; }

public string CreationDate { get; set; }

 

public AuthorAttribute(string name)

{

Name = name;

}

}

Для применения атрибута язык C# поддерживает следующий синтаксис: имя класса атрибута записывается в квадратных скобках перед тем элементом, к которому он относится. При этом разрешено указывать имя атрибута без суффикса Attribute. Применение атрибута условно соответствует созданию объекта. Поэтому после имени атрибута указываются в круглых скобках аргументы конструктора атрибута. Если у атрибута конструктор без параметров, круглые скобки можно не писать. Наряду с аргументами конструктора можно указать именованные параметры, предназначенные для задания значения открытого поля или свойства. Для этого используется синтаксис имя-элемента = значение. Именованные параметры всегда записываются в конце списка аргументов конструктора. Ниже приведены примеры применения AuthorAttribute.

[Author(" Brian Kernighan", CreationDate = " 01.01.2012")]

public class ColorPlugin

{

[Author(" Dennis Ritchie")]

public void Process() { }

}

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

// атрибут Author можно многократно применить к классу или методу

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,

AllowMultiple = true)]

public class AuthorAttribute: Attribute

{

// элементы класса для краткости не приводятся

}

Синтаксис применения атрибутов позволяет указать в квадратных скобках несколько атрибутов через запятую. Если возникает неоднозначность трактовки цели атрибута, то нужно указать перед именем атрибута специальный префикс – assembly, module, field, event, method, param, property, return, type.

// применение атрибута к сборке

[assembly: AssemblyKeyFile(" keys.snk")]

 

// многократное применение атрибута

[Author(" Brian Kernighan"), Author(" Dennis Ritchie")]

public class ColorPlugin { }

Опишем возможности получения информации о применённых атрибутах. Метод Attribute.GetCustomAttributes() возвращает все атрибуты некоторого элемента в виде массива. Метод Attribute.GetCustomAttribute() получает атрибут заданного типа:

Attribute GetCustomAttribute(MemberInfo element, Type attributeType)

При помощи параметра element задаётся элемент, у которого надо получить атрибут. Второй параметр – это тип получаемого атрибута.

// пример получения атрибута

var author = Attribute.GetCustomAttribute(typeof (ColorPlugin),

typeof (AuthorAttribute));

if (author! = null)

{

Console.WriteLine(((AuthorAttribute) author).Name);

}

Платформа.NET предоставляет для использования обширный набор атрибутов, некоторая часть которых представлена в табл. 19.

Таблица 19

Некоторые атрибуты, применяемые в платформе.NET

Атрибут Цель применения Описание
[AttributeUsage] Класс Задаёт область применения класса-атрибута
[Conditional] Метод Компилятор может игнорировать вызовы помеченного метода при заданном условии
[DllImport] Метод Импорт функций из DLL
[MTAThread] Метод Main() Для приложения используется модель COM Multithreaded apartment
[NonSerialized] Поле Указывает, что поле не будет сериализовано
[Obsolete] Кроме param, assembly, module, return Информирует, что в будущих реализациях данный элемент может отсутствовать
[ParamArray] Параметр Позволяет одиночному параметру быть обработанным как набор параметров params
[Serializable] Класс, структура, перечисление, делегат Указывает, что все поля типа могут быть сериализованы
[STAThread] Метод Main() Для приложения используется модель COM Single-threaded apartment
[StructLayout] Класс, структура Задаёт схему размещения данных класса или структуры в памяти (Auto, Explicit, Sequential)
[ThreadStatic] Статическое поле В каждом потоке будет использоваться собственная копия данного статического поля

Рассмотрим единичный пример использования стандартных атрибутов. Атрибуты применяются для настройки взаимодействия программ платформы.NET и библиотек на неуправляемом коде. Атрибут [DllImport] предназначен для импортирования функций из библиотек динамической компоновки, написанных на неуправляемом коде. В следующей программе показан импорт системной функции MessageBoxA():

using System.Runtime.InteropServices;

 

public class MainClass

{

[DllImport(" user32.dll")]

public static extern int MessageBoxA(int hWnd, string text,

string caption, uint type);

 

public static void Main()

{

MessageBoxA(0, " Hello World", " Unmanaged DLL", 0);

}

}

Для использования атрибута [DllImport] требуется подключить пространство имён System.Runtime.InteropServices. Кроме этого, необходимо объявить импортируемую функцию статической и пометить её модификатором extern. Атрибут [DllImport] допускает использование дополнительных аргументов, подробное описание которых можно найти в документации MSDN.

Исполняемая среда.NET выполняет корректную передачу аргументов примитивных типов между управляемым и неуправляемым кодом. Для правильной передачи сложных аргументов требуется использование специального атрибута [StructLayout] при объявлении пользовательского типа. Например, пусть выполняется экспорт системной функции GetLocalTime():

[DllImport(" kernel32.dll")]

public static extern void GetLocalTime(SystemTime st);

В качестве параметра функция использует объект класса SystemTime. Этот класс должен быть описан следующим образом:

[StructLayout(LayoutKind.Sequential)]

public class SystemTime

{

public ushort wYear;

public ushort wMonth;

public ushort wDayOfWeek;

public ushort wDay;

public ushort wHour;

public ushort wMinute;

public ushort wSecond;

public ushort wMilliseconds;

}

Атрибут [StructLayout] с аргументом LayoutKind.Sequential указывает, что поля объекта должны быть расположены в памяти в точности так, как это записано в объявлении класса. В противном случае при работе с системной функцией вероятно возникновение ошибок.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.