Глава.18 .Настраиваемые.атрибуты
CanWriteCheck(new Program());
}
private static void CanWriteCheck(Object obj) {
// Создание и инициализация экземпляра типа атрибута
Attribute checking = new AccountsAttribute(Accounts.Checking);
// Создание экземпляра атрибута, примененного к типу
Attribute validAccounts =
obj.GetType().GetCustomAttribute(false);
// Если атрибут применен к типу и указывает на счет "Checking",
// значит, тип может выписывать чеки
if ((validAccounts != null) && checking.Match(validAccounts)) {
Console.WriteLine("{0} types can write checks.", obj.GetType());
} else {
Console.WriteLine("{0} types can NOT write checks.", obj.GetType());
}
}
}
Построение и запуск этого приложения приводит к следующему результату:
ChildAccount types can NOT write checks.
AdultAccount types can write checks.
Program types can NOT write checks.
Выявление настраиваемых
атрибутов без создания объектов,
производных от Attribute
В этом разделе мы поговорим об альтернативном способе выявления настраи-
ваемых атрибутов, примененных к метаданным. В ситуациях, требующих повы-
шенной безопасности, этот способ гарантированно предотвращает выполнение
кода класса, производного от
Attribute
. Вообще говоря, при вызове методов
GetCustomAttribute(s)
типа
Attribute
вызывается конструктор класса атрибута
и методы, задающие значения свойств. А первое обращение к типу заставляет CLR
вызвать конструктор этого типа (если он, конечно, существует). Конструктор, метод
доступа
set
и методы конструктора типа могут содержать код, выполняющийся
при каждом поиске атрибута. Возможность выполнения в домене приложения не-
известного кода создает потенциальную угрозу безопасности.
Для обнаружения атрибутов без выполнения кода класса атрибута применяется
класс
System.Reflection.CustomAttributeData
. В нем определен единственный
статический метод
GetCustomAttributes
, позволяющий получить информацию
о примененных атрибутах. Этот метод имеет четыре перегруженные версии: одна
481
Выявление.настраиваемых.атрибутов.без.создания.объектов
принимает параметр типа
Assembly
, другая —
Module
, третья —
ParameterInfo
, по-
следняя —
MemberInfo
. Класс определен в пространстве имен
System.Reflection
,
о котором будет рассказано в главе 23. Обычно класс
CustomAttributeData
ис-
пользуется для анализа метаданных сборки, загружаемой статическим методом
ReflectionOnlyLoad
класса
Assembly
(он также рассматривается в главе 23). Пока
же достаточно сказать, что этот метод загружает сборку таким образом, что CLR не
может выполнять какой-либо код, в том числе конструкторы типов.
Метод
GetCustomAttributes
класса
CustomAttributeData
работает как ме-
тод-фабрика: он возвращает набор объектов
CustomAttributeData
в объекте типа
IList
. Каждому элементу этой коллекции соответствует
один настраиваемый атрибут. Для каждого объекта класса
CustomAttributeData
можно запросить предназначенные только для чтения свойства, определив в ре-
зультате, каким способом
мог бы быть
сконструирован и инициализирован объект.
Например, свойство
Constructor
указывает, какой именно конструктор
мог бы быть
вызван. Свойство
ConstructorArguments
возвращает аргументы, которые
могли бы
быть
переданы конструктору в качестве экземпляра
IListArgument>
. Свойство
NamedArguments
возвращает поля и свойства, которые
могли
бы быть
заданы как экземпляр
IList
. Условное
наклонение во всех этих предложениях обусловлено тем, что ни конструктор, ни
метод доступа
set
на самом деле не вызываются. Для безопасности запрещено вы-
полнение любых методов класса атрибута.
Ниже приведена измененная версия предыдущего кода, в которой для безопас-
ного получения атрибутов используется класс
CustomAttributeData
:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Collections.Generic;
[assembly: CLSCompliant(true)]
[Serializable]
[DefaultMemberAttribute("Main")]
[DebuggerDisplayAttribute("Richter", Name="Jeff", Target=typeof(Program))]
public sealed class Program {
[Conditional("Debug")]
[Conditional("Release")]
public void DoSomething() { }
public Program() {
}
[CLSCompliant(true)]
[STAThread]
public static void Main() {
// Вывод атрибутов, примененных к данному типу
ShowAttributes(typeof(Program));
продолжение
482
Do'stlaringiz bilan baham: |