Чтение онлайн

на главную - закладки

Жанры

Полное руководство. С# 4.0
Шрифт:

Рассмотрим следующий пример, демонстрирующий полностью автоматизирован ное обнаружение типов. В этом примере сначала загружается сборка MyClasses.ехе, затем конструируется объект класса MyClass и далее вызываются все методы, объяв ленные в классе MyClass, причем о них ничего заранее неизвестно. // Использовать класс MyClass, ничего не зная о нем заранее. using System; using System.Reflection; class ReflectAssemblyDemo { static void Main { int val; Assembly asm = Assembly.LoadFrom("MyClasses.exe"); Type[] alltypes = asm.GetTypes; Type t = alltypes[0]; // использовать первый обнаруженный класс Console.WriteLine("Использовано: " + t.Name); ConstructorInfo[] ci = t.GetConstructors; // Использовать первый обнаруженный конструктор. ParameterInfо[] cpi = ci[0].GetParameters; object reflectOb; if(cpi.Length > 0) { object[] consargs = new object[cpi.Length]; //

Инициализировать аргументы. fox(int n=0; n < cpi.Length; n++) consargs[n] = 10 + n * 20; // Сконструировать объект. reflectOb = ci[0].Invoke(consargs); } else reflectOb = ci[0].Invoke(null); Console.WriteLine("\nВызов методов для объекта reflectOb."); Console.WriteLine; // Игнорировать наследуемые методы. MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); // Вызвать каждый метод. foreach(Methodlnfo m in mi) { Console.WriteLine("Вызов метода {0} ", m.Name); // Получить параметры. ParameterInfo[] pi = m.GetParameters; // Выполнить методы. switch(pi.Length) { case 0: // аргументы отсутствуют if(m.ReturnType == typeof(int)) { val = (int) m.Invoke(reflectOb, null); Console.WriteLine("Результат: " + val); } else if(m.ReturnType == typeof(void)) { m.Invoke(reflectOb, null); } break; case 1: // один аргумент if(pi[0].ParameterType == typeof(int)) { object[] args = new object[1]; args[0] = 14; if((bool) m.Invoke(reflectOb, args)) Console.WriteLine("Значение 14 находится между x и у"); else Console.WriteLine("Значение 14 не находится между х и у"); } break; case 2: // два аргумента if((pi[0].ParameterType == typeof(int)) && (pi[1].ParameterType == typeof (int))) { object[] args = new object[2]; args[0] = 9; args[1] = 18; m.Invoke(reflectOb, args); } else if((pi[0].ParameterType == typeof(double)) && (pi[1].ParameterType == typeof(double))) { object[] args = new object[2]; args[0] = 1.12; args[1] = 23.4; m.Invoke(reflectOb, args); } break; } Console.WriteLine; } } }

Эта программа дает следующий результат. Использовано: MyClass Конструирование класса MyClass(int). Значение х: 10, значение у: 10 Вызов методов для объекта reflectOb. Вызов метода Sum Результат: 20 Вызов метода IsBetween Значение 14 не находится между х и у Вызов метода Set В методе Set(int, int). Значение х: 9, значение у: 18 Вызов метода Set В методе Set(double, double). Значение х: 1, значение у: 23 Вызов метода Show Значение х: 1, значение у: 23

Эта программа работает довольно просто, но все же требует некоторых пояснений. Во-первых, получаются и используются только те методы, которые явно объявлены в классе MyClass. Для этой цели служит форма BindingFlags метода GetMethods, чтобы воспрепятствовать вызову методов, наследуемых от объекта. И во-вторых, ко личество параметров и возвращаемый тип каждого метода получаются динамически, а затем определяются и проверяются в операторе switch. На основании этой инфор мации формируется вызов каждого метода. Атрибуты

В C# разрешается вводить в программу информацию декларативного характера в форме атрибута, с помощью которого определяются дополнительные сведения (метаданные), связанные с классом, структурой, методом и т.д. Например, в програм ме можно указать атрибут, определяющий тип кнопки, которую должен отображать конкретный класс. Атрибуты указываются в квадратных скобках перед тем элементом, к которому они применяются. Следовательно, атрибут не является членом класса, но обозначает дополнительную информацию, присоединяемую к элементу. Основы применения атрибутов

Атрибут поддерживается классом, наследующим от класса System.Attribute. Поэтому классы атрибутов должны быть подклассами класса Attribute. В классе Attribute определены основные функциональные возможности, но далеко не все они нужны для работы с атрибутами. В именах классов атрибутов принято употреблять суффикс Attribute. Например, ErrorAttribute — это имя класса атрибута, опи сывающего ошибку.

При объявлении класса атрибута перед его именем указывается атрибут AttributeUsage. Этот встроенный атрибут обозначает типы элементов, к которым может применяться объявляемый атрибут. Так, применение атрибута может ограни чиваться одними методами. Создание атрибута

В классе атрибута определяются члены, поддерживающие атрибут. Классы

атри бутов зачастую оказываются довольно простыми и содержат небольшое количество полей или свойств. Например, атрибут может определять примечание, описывающее элемент, к которому присоединяется атрибут. Такой атрибут может принимать сле дующий вид. [AttributeUsage(AttributeTargets.All)] public class RemarkAttribute : Attribute { string pri_remark; // базовое поле свойства Remark public RemarkAttribute(string comment) { pri_remark = comment; } public string Remark { get { return pri_remark; } } }

Проанализируем этот класс атрибута построчно.

Объявляемый атрибут получает имя RemarkAttribute. Его объявлению пред шествует встроенный атрибут AttributeUsage, указывающий на то, что атрибут RemarkAttribute может применяться ко всем типам элементов. С помощью встроен ного атрибута AttributeUsage можно сузить перечень элементов, к которым может присоединяться объявляемый атрибут. Подробнее о его возможностях речь пойдет далее в этой главе.

Далее объявляется класс RemarkAttribute, наследующий от класса Attribute. В классе RemarkAttribute определяется единственное закрытое поле pri_remark, поддерживающее одно открытое и доступное для чтения свойство Remark. Это свой ство содержит описание, связываемое с атрибутом. (Конечно, Remark можно было бы объявить как автоматически реализуемое свойство с закрытым аксессором set, но ради наглядности данного примера выбрано свойство, доступное только для чтения.) В данном классе определен также один открытый конструктор, принимающий стро ковый аргумент и присваивающий его свойству Remark. Этим пока что ограничивают ся функциональные возможности класса RemarkAttribute, готового к применению. Присоединение атрибута

Как только класс атрибута будет определен, атрибут можно присоединить к эле менту. Атрибут указывается перед тем элементом, к которому он присоединяется, и для этого его конструктор заключается в квадратные скобки. В качестве примера ниже показано, как атрибут RemarkAttribute связывается с классом. [RemarkAttribute("В этом классе используется атрибут.")] class UseAttrib { // ... }

В этом фрагменте кода конструируется атрибут RemarkAttribute, содержащий комментарий "В этом классе используется атрибут." Данный атрибут затем связывается с классом UseAttrib.

Присоединяя атрибут, совсем не обязательно указывать суффикс Attribute. Например, приведенный выше класс может быть объявлен следующим образом. [Remark("В этом классе используется атрибут.")] class UseAttrib { // ... }

В этом объявлении указывается только имя Remark. Такая сокращенная форма счи тается вполне допустимой, но все же надежнее указывать полное имя присоединяемо го атрибута, чтобы избежать возможной путаницы и неоднозначности. Получение атрибутов объекта

Как только атрибут будет присоединен к элементу, он может быть извлечен в дру гих частях программы. Для извлечения атрибута обычно используется один из двух методов. Первый метод, GetCustomAttributes, определяется в классе MemberInfо и наследуется классом Туре. Он извлекает список всех атрибутов, присоединенных к элементу. Ниже приведена одна из его форм. object[] GetCustomAttributes(bool наследование)

Если наследование имеет логическое значение true, то в список включаются атрибуты всех базовых классов, наследуемых по иерархической цепочке. В противном случае атрибуты извлекаются только из тех классов, которые определяются указанным типом.

Второй метод, GetCustomAttribute, определяется в классе Attribute. Ниже приведена одна из его форм: static Attribute GetCustomAttribute(MemberInfo элемент, Type тип_атрибута)

где элемент обозначает объект класса MemberInfo, описывающий тот элемент, для ко торого создаются атрибуты, тогда как тип_атрибута — требуемый атрибут. Данный метод используется в том случае, если имя получаемого атрибута известно заранее, что зачастую и бывает. Так, если в классе UseAttrib имеется атрибут RemarkAttribute, то для получения ссылки на этот атрибут можно воспользоваться следующей после довательностью кода. // Получить экземпляр объекта класса MemberInfо, связанного // с классом, содержащим атрибут RemarkAttribute. Type t = typeof(UseAttrib); // Извлечь атрибут RemarkAttribute. Type tRemAtt = typeof(RemarkAttribute); RemarkAttribute ra = (RemarkAttribute) Attribute.GetCustomAttribute(t, tRemAtt);

Поделиться:
Популярные книги

Жалкая

Макинтайер Эмили
3. Долго и Несчастливо
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Жалкая

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец

Академия проклятий. Книги 1 - 7

Звездная Елена
Академия Проклятий
Фантастика:
фэнтези
8.98
рейтинг книги
Академия проклятий. Книги 1 - 7

Измена. Верни мне мою жизнь

Томченко Анна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Верни мне мою жизнь

Измена

Рей Полина
Любовные романы:
современные любовные романы
5.38
рейтинг книги
Измена

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сердце для стража

Каменистый Артем
5. Девятый
Фантастика:
фэнтези
боевая фантастика
9.20
рейтинг книги
Сердце для стража

Черный Маг Императора 11

Герда Александр
11. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Черный Маг Императора 11

Имя нам Легион. Том 3

Дорничев Дмитрий
3. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 3

Жена фаворита королевы. Посмешище двора

Семина Дия
Фантастика:
фэнтези
5.00
рейтинг книги
Жена фаворита королевы. Посмешище двора

Как я строил магическую империю 5

Зубов Константин
5. Как я строил магическую империю
Фантастика:
попаданцы
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 5

Блуждающие огни 2

Панченко Андрей Алексеевич
2. Блуждающие огни
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Блуждающие огни 2

Ратник

Ланцов Михаил Алексеевич
3. Помещик
Фантастика:
альтернативная история
7.11
рейтинг книги
Ратник

Маленькая слабость Дракона Андреевича

Рам Янка
1. Танцы на углях
Любовные романы:
современные любовные романы
эро литература
5.25
рейтинг книги
Маленькая слабость Дракона Андреевича