![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Атрибуты
Платформа.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
Рассмотрим единичный пример использования стандартных атрибутов. Атрибуты применяются для настройки взаимодействия программ платформы.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 указывает, что поля объекта должны быть расположены в памяти в точности так, как это записано в объявлении класса. В противном случае при работе с системной функцией вероятно возникновение ошибок.
|