Теория и задания по Си-Шарп (КФУ). Учебное пособие казань 2017 2 удк 681 06 ббк 32. 973 Печатается по постановлению Редакционноиздательского совета
![]()
|
ГЛАВА 14. АТРИБУТЫ Атрибуты – инструмент для добавления метаданных в классы, для изменения поведения объекта во время выполнения, для получения информации о транзакции объекта, также используется для передачи дополнительной информации, носящей описательный характер, разработчику. Атрибут – тэг для предоставления информации во время выполнения о поведении программных элементов, таких как классы, перечисления, сборки. Информация об атрибутах хранится в метаданных, связанных с элементом. Атрибуты можно применять к разным программным элементам: сборкам, модулям, классам, структурам, перечислениям, конструкторам, методам, свойствам, полям, событиям, интерфейсам, параметрам, возвращаемым значениям и делегатам. Синтаксис: [атрибут (позиционные_параметры, именованные_параметры=значение, …)] элемент, к которому применяется атрибут. Сначала задается имя атрибута, затем в скобках передаются позиционные параметры, затем – именованные. Позиционные параметры используются для передачи важной информации, именованные – для передачи дополнительных сведений. Для одного элемента можно задать несколько атрибутов в разных квадратных скобках [ ], или через запятую в одних квадратных скобках. В .NET Framework определено большое количество атрибутов. Рассмотрим некоторые из них. Условный атрибут используется при отладке кода. Вызывает условную компиляцию метода, для которого этот атрибут задан. using System.Diagnostics; class MyClass { [Conditional(“DEBUGGING”)] // задаем условный атрибут для метода //MyMethod public static void MyMethod() { … } } 107 Где идентификатор DEBUGGING определяется следующим образом: #define DEBUGGING Class AnotherClass { public static void Test() { MyClass.MyMethod(); } } Если параметр компиляции не задан, не задана строка #define DEBUGGING или соответствующая строка не указана в опции компилятора, то вызов MyMethod будет пропущен. Метод, к которому применяется условный атрибут, должен возвращать void, не может быть override и не должен быть методом, определяющим интерфейс. Атрибут DLLImport используется для вызова неуправляемого кода в программе С#. Неуправляемый код – это термин для кода разработанного вне среды .NET(например, программа на стандартном С откомпилированная в файл dll). При помощи этого атрибута можно вызывать внешние методы из неуправляемых dll. При вызове внешнего метода, общая среда выполнения определяет DLL, загружает её в память процесса, преобразует параметры, если это необходимо, и передает управление адресу начала неуправляемого кода. using System.Runtime.InteropService; … public class MyClass() { [DLLImport(“MyDll.dll”, EntryPoint=”MyFunction”)] public static extern int MyFunction(string param1); … int result = MyFunction(“Привет из неуправляемого кода”); … } У атрибута DLLImport два параметра: первый параметр – имя DLL библиотеки, второй – имя внешней функции. 108 Пользовательские атрибуты В .NET можно создать свои собственные атрибуты. Также как и предопределенные атрибуты, они связаны с каким-то элементом программы, хранятся в их метаданных и обеспечены механизмом получения значения атрибута. Для создания собственного атрибута создается пользовательский класс, наследник от класса System.Attribute. Перед классом указывается атрибут AttributeUsage, который определяет, к какому элементу класса будет привязан пользовательский атрибут. Если элементов несколько, то используется оператор | для их связи: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor)] public class MyAttribute: System.Attribute { … } Все классы атрибутов должны иметь конструктор, который использует позиционные параметры. Для работы с именованными параметрами задаются перегруженные конструкторы. Класс атрибута может содержать свойства для задания именованных параметров. Например, атрибут DeveloperInfo содержит позиционный строковый параметр и именованный Date. [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor)] public class DeveloperInfoAttribute:System.Attribute { public DeveloperInfoAttribute(string developer) { … } public string Date { get { … } set { … } } } [DeveloperInfoAttribute(“Bert”, Date = “08-28-2009” )] public class MyClass 109 { … } Во время компиляции при встрече атрибута происходит следующая последовательность действий: 1. Поиск класса атрибута. 2. Проверка области атрибута. 3. Проверка конструктора. 4. Создание объекта. 5. Проверка именованных параметров. 6. Установка значений именованных параметров. 7. Сохранение состояния объекта атрибута в метаданных связанного элемента. Для того чтобы для одного элемента можно было задать несколько атрибутов, необходимо при объявлении класса атрибута установить параметр AllowMultiple=true: [AttributeUsage(AttributeTergets.Class, AllowMultiple = true)] Для получения информации, хранящейся в метаданных, среда .NET Framework использует механизм, называющийся рефлексией. Пространство имен System.Reflection содержит классы для извлечения метаданных. Класс MemberInfo используется для получения информации об атрибутах компонента и обеспечивает доступ к метаданным его членов. Для заполнения массива MemberInfo используется метод GetMembers объекта System.Type. System.Reflection.MemberInfo[] memberInfoArray; memberInfoArray = typeof(MyClass).GetMembers(); Для получения информации о пользовательских атрибутах есть специальный метод GetCustomAttributes объекта MemberInfo. System.Reflection.MemberInfo typeInfo; typeInfo = typeof(MyClass); object[] attrs = typeInfo.GetCustomAttributes(false); 110 После получения массива атрибутов, можно проверить их значения. foreach(Attribute atr in attrs){ if(atr is DeveloperInfoAttribute){ DeveloperInfoAttribute dia = (DeveloperInfoAttribute) atr; Console.WriteLine(“{0} {1}”, dia.Developer, dia.Date); } } Если нет ни одного атрибута для класса, то метод возвращает null. Кроме того, можно проверить наличие атрибута при помощи метода IsDefined. Type devInfoAttrType = typeof(DeveloperInfoAttribute); if(typeInfo.IsDefined(devInfoAttrType, false)) object[] attrs = typeInfo.GetCustomAttributes(devInfoAttrType,false); Вопросы к разделу 1. Можно ли отметить один объект класса используя атрибут? 2. Где хранятся значения атрибутов? 3. Какой механизм используется для определения значения атрибутов при выполнении приложения? Лабораторная работа Задания на использование условного атрибута(ConditionalАttribute), создание пользовательского атрибута. Время, необходимое на выполнение задания 45 мин. Упражнение 14.1 Использование предопределенного условного атрибута для условного выполнения кода (указывает компиляторам, что при отсутствии символа условной компиляции, вызов метода или атрибут следует игнорировать). В классе банковский счет добавить метод DumpToScreen, который отображает детали банковского счета. Для выполнения этого метода использовать условный атрибут, зависящий от символа условной компиляции DEBUG_ACCOUNT. Протестировать метод DumpToScreen. Упражнение 14.2 Создать пользовательский атрибут DeveloperInfoAttribute. Этот атрибут позволяет хранить в метаданных класса имя разработчика и, дополнительно, дату разработки класса. Атрибут должен 111 позволять многократное использование. Использовать этот атрибут для записи имени разработчика класса рациональные числа (упражнение 12.2). Домашнее задание 14.1 Создать пользовательский атрибут для класса из домашнего задания 13.1. Атрибут позволяет хранить в метаданных класса имя разработчика и название организации. Протестировать. Учебное издание Александрова Ирина Леонидовна Тумаков Дмитрий Николаевич ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ C# Учебное пособие Подписано в печать 14.11.2017 г. Форм. бум. 60 × 84 1/16. Гарнитура "Таймс". Печать цифровая. Печ. л. 8,25. Т.100. Заказ 12. Лаборатория оперативной полиграфии Издательства КГУ 420008, Казань, ул. пр Нужина, 1/37, +7 (843) 233-73-28, +7 (843) 233-73-59 |