Полностью автоматизированное обнаружение типов



 

Прежде чем завершить рассмотрение рефлексии, обратимся к еще одному поучительному примеру. Несмотря на то что в программе из предыдущего примера класс MyClass был полноценно использован без явного указания на его имя в программе, этот пример все же опирается на предварительную осведомленность о содержимом класса MyClass. Так, в программе были заранее известны имена методов Set и Sum из этого класса. Но с помощью рефлексии можно воспользоваться типом данных, ничего не зная о нем заранее. С этой целью придется извлечь все сведения, необходимые для конструирования объекта и формирования вызовов соответствующих методов. Такой подход может оказаться пригодным, например, при создании инструментального средства визуального проектирования, поскольку он позволяет использовать типы данных, имеющиеся в системе.

Рассмотрим следующий пример, демонстрирующий полностью автоматизированное обнаружение типов. В этом примере сначала загружается сборка 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();

 

Использовать первый обнаруженный конструктор.

ParameterInfo[] cpi = ci[0].GetParameters();

object reflectOb;

 

if (cpi.Length > 0) {

object[] consargs = new object[cpi.Length];

 

// Инициализировать аргументы,  

for (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 (MethodInfo 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 {


Дата добавления: 2019-02-12; просмотров: 252; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!