|
Программирование >> Программирование с использованием ajax
Многие из этих значений применяются редко, поскольку обычно область действия атрибута не вызывает сомнений. Однако значения assembly, module и return требуют использования флага области действия. При наличии определенных сомнений относительно того, где атрибут определен, компилятор выбирает объект, которому атрибут будет присвоен. Чаще всего это происходит при присвоении атрибута возвращаемому значению функции, как показано в следующем примере: [SomeAttribute] public string DoSomething (); В данном случае компилятор решает, что атрибут применяется к методу, а не к возвращаемому значению. Для достижения требуемого эффекта нужно следующим образом определить область действия атрибута: [return:SomeAttribute] public string DoSomething (); AttributeUsage. AIIowMuI tiple Этот атрибут определяет возможность добавления пользователем одного или более одинаковых атрибутов к элементу. Синтаксис установки флага AllowMultiple несколько необычен. Конструктор AttributeUsage принимает только один параметр - список флагов возможного применения атрибута. AllowMultiple - свойство атрибута AttributeUsage, поэтому следующая синтаксическая конструкция означает создать атрибут, а затем установить значение свойства AllowMultiple равным true : [AttributeUsage (AttributeTargets.Class AttributeTargets.Property I AttributeTargets.Method I AttributeTargets.Constructor , AllowMultiple=true)] public class BugFixAttribute : Attribute Аналогичный метод используется для установки свойства Inherited. Если пользовательский атрибут обладает свойствами, их можно установить аналогичным образом. Возможный пример - добавление имени лица, исправившего ошибку: public readonly string BugNumber; public readonly string Comments; public readonly string Authors-public override string ToString () { if (string. IsNullOrEn5>ty (Author)) return string.Format ( BugFix {0} : {1} , BugNumber , Comments); else return string.Format ( BugFix {0} by {1} : {2) , BugNumber , Author , Comments) ; Этот код добавляет поле Author и перегруженную реализацию метода ToString (), которая отображает все сведения, если поле Author установлено. Если свойство Author не определено во время присвоения атрибута коду, вывод атрибута BugFix отображает только номер ошибки и комментарии. Метод ToString () будет использоваться для отображения списка исправленных ошибок в данном фрагменте кода - возможно, для печати и записи в какой-либо файл. После того как атрибут BugFix создан. нам потребуется какой-то способ формирования отчета об исправлениях, выполненных в классе и членах этого класса. Доступный способ создания отчета об исправленных ошибках класса - передача типа класса (в очередной раз System.Туре) следующей функции DisplayFixes. Эта функция использует также рефлексию для отыскания любых исправлений ошибок, примененных к классу, а затем просматривает все методы данного класса, отыскивая в них атрибуты BugFix: public static void DisplayFixes (System.Type t) { Получение всех исправления ошибок для данного типа, который считается классом. object[] fixes = t.GetCustomAttributes (typeof (BugFixAttribute) , false); Console.WriteLine ( Displaying fixes for {0} , t) ; Console.WriteLine ( Отображение исправлений для {0} , t) ; Отображение информации об основных исправлениях, foreach (BugFixAttribute bugFix in fixes) Console.WriteLine ( {0} , bugFix); Получение всех членов (т.е. функций) класса. foreach (Memberlnfo member in t.GetMembers (BindingFlags.Instance I BindingFlags.Public BindingFlags.Nonpublic BindingFlags.Static)) И отыскание любых значительных изменений примененных к ним. object[] memberFixes = member.GetCustomAttributes(typeof(BugFixAttribute) , false); if (memberFixes.Length > 0) { Console.WriteLine ( {0} , member.Name); Циклический просмотр и отображение информации об этих исправлениях, foreach (BugFixAttribute memberFix in memberFixes) Console.WriteLine ( {0} , memberFix); Сначала код извлекает все атрибуты BugFix из самого типа: object[] fixes = t.GetCustomAttributes (typeof (BugFixAttribute), false); Эти атрибуты нумеруются и отображаются. Затем код с помощью метода GetMembers () циклически просматривает все члены, определенные в классе: foreach (Memberlnfo member in t.GetMembers ( BindingFlags.Instance I BindingFlags.Public I BindingFlags.Nonpublic BindingFlags.Static)) Метод GetMembers извлекает свойства, методы и поля из данного типа. Для ограничения списка возвращенных членов служит перечисление BindingFlags (определенное внутри System. Ref lection). Флаги связывания, переданные этому методу, указывают интересующие члены - в данном случае нас интересуют все члены экземпляров и статические члены, независимо от видимости, поэтому мы указываем члены Instance и Static, а также Public и Nonpublic. После извлечения всех членов мы проходим по ним циклом, отыскивая любые атрибуты BugFix, связанные с конкретным членом, и выводим их на консоль. Чтобы вывести список исправления ошибок для данного класса, достаточно вызвать статический метод DisplayFixes (), передавая ему тип класса: BugFixAttribute.DisplayFixes (typeof (MyBuggyCode)); Для ранее представленного класса MyBuggyCode это приводит к следующему выводу: Displaying fixes for MyBuggyCode BugFix 101 : Created some methods DoSomething BugFix 2112 : Returned a non-null string BugFix 38382 : Returned OK . ctor BugFix 90125 : Removed call to base() Если бы нужно было отобразить исправления для всех классов данной сборки, можно было бы воспользоваться рефлексией для извлечения всех типов из сборки и передать каждый из них статическому методу BugFixAttribute. DisplayFixes. AttributeUsage. Inherited Посредством установки этого флага при определении пользовательского атрибута атрибут можно определить как наследуемый: [AttributeUsage (AttributeTargets.Class, Inherited = true)] public class BugFixAttribute { . . . } Этот код указывает, что атрибут BugFix будет наследоваться любыми подклассами класса, который использует атрибут, что может быть как желательным, так и не желательным. В случае атрибута BugFix такое поведение, вероятно, нежелательно, поскольку обычно исправление ошибок применяется к отдельному классу, но не к его производным классам. Предположим, существует следующий абстрактный класс с примененным исправлением ошибки: [BugFix( 38383 , Fixed that abstract bug )] public abstract class GenericRow : DataRow { public GenericRow (System.Data.DataRowBuilder builder) : base (builder) При создании подкласса этого класса нежелательно, чтобы этот же атрибут BugFix был отражен в подклассе - подкласс не содержит этого исправления. Однако при определении набора атрибутов, которые связывают члены класса с полями таблицы базы данных, очевидно, эти атрибуты наследовать желательно. Теперь, располагая определенными знаниями о пользовательских атрибутах, легко представить себе несколько ситуаций, когда добавление дополнительной информации о сборках полезно. Можно было бы также расширить определенный ранее атрибут BugFix - например, для определения номера версии программы, в которой
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |