If ((bool)m.Invoke(reflectOb, args))



Console.WriteLine("Значение 14 находится между x и у");

}

else if (m.Name.CompareTo("Show") == 0) {

m.Invoke(reflectOb, null);

}

}

}

}

 

Эта программа дает следующий результат.

 

Доступные конструкторы:

MyClass(Int32 i)

MyClass(Int32 i, Int32 j)

Найден конструктор с двумя параметрами.

Конструирование класса MyClass(int, int)

Значение х: 10, значение у: 20

Вызов методов для объекта reflectOb

Сумма равна 30

Значение 14 находится между х и у

В методе Set(int, int). Значение х: 9, значение у: 18

В методе Set(double, double). Значение х: 1, значение у: 23

Значение х: 1, значение у: 23

 

А теперь рассмотрим порядок применения рефлексии для конструирования объекта класса MyClass. Сначала получается перечень открытых конструкторов в следующей строке кода.

 

ConstructorInfo[] ci = t.GetConstructors();

 

Затем для наглядности примера выводятся полученные конструкторы. После этого осуществляется поиск по списку конструктора, принимающего два аргумента, как показано в приведенном ниже фрагменте кода.

 

for(x=0; х < ci.Length; х++) {

ParameterInfo[] pi = ci[x].GetParameters();

if(pi.Length == 2) break;

}

 

Если такой конструктор найден, как в данном примере, то в следующем фрагменте кода получается экземпляр объекта заданного типа.

 

// Сконструировать объект,  

object[] consargs = new object[2];

consargs[0] = 10;

consargs[1] = 20;

object reflectOb = ci[x].Invoke(consargs);

 

После вызова метода Invoke() переменная экземпляра reflectOb будет ссылаться на объект типа MyClass. А далее в программе выполняются соответствующие методы для экземпляра этого объекта.

Следует, однако, иметь в виду, что ради простоты в данном примере предполагается наличие лишь одного конструктора с двумя аргументами типа int. Очевидно, что в реальном коде придется дополнительно проверять соответствие типов каждого параметра и аргумента.

 

 

Получение типов данных из сборок

 

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

Как следует из главы 16, сборка несет в себе сведения о типах классов, структур и прочих элементов данных, которые в ней содержатся. Прикладной интерфейс Reflection API позволяет загрузить сборку, извлечь сведения о ней и получить экземпляры объектов любых открыто доступных в ней типов. Используя этот механизм, программа может выявлять свою среду и использовать те функциональные возможности, которые могут оказаться доступными без явного их определения во время компиляции. Это очень эффективный и привлекательный принцип. Представьте себе, например, программу, которая выполняет роль "браузера типов", отображая типы данных, доступные в системе, или же инструментальное средство разработки, позволяющее визуально составлять программы из различных типов данных, поддерживаемых в системе. А поскольку все сведения о типах могут быть извлечены и проверены, то ограничений на применение рефлексии практически не существует.

Для получения сведений о сборке сначала необходимо создать объект класса Assembly. В классе Assembly открытый конструктор не определяется. Вместо этого объект класса Assembly получается в результате вызова одного из его методов. Так, для загрузки сборки по заданному ее имени служит метод LoadFrom(). Ниже приведена его соответствующая форма:

 

Static Assembly LoadFrom(string файл_сборки)

 

где файл_ сборки -обозначает конкретное имя файла сборки.

Как только будет получен объект класса Assembly, появится возможность обнаружить определенные в нем типы данных, вызвав для него метод GetTypes() в приведенной ниже общей форме.

 

Туре [] GetTypes()

 

Этот метод возвращает массив типов, содержащихся в сборке.

Для того чтобы продемонстрировать порядок обнаружения типов в сборке, потребуются два исходных файла. Первый файл будет содержать ряд классов, обнаруживаемых в коде из второго файла. Создадим сначала файл MyClasses.cs, содержащий следующий код.

 

// Файл, содержащий три класса и носящий имя MyClasses.cs.

using System;

 

class MyClass {

int x;

int y;

 

public MyClass(int i) {

Console.WriteLine("Конструирование класса MyClass(int). ");

x = y = i;

Show();

}

public MyClass(int i, int j) {

Console.WriteLine("Конструирование класса MyClass(int, int). ");

x = i;

y = j;

Show();

}

 

public int Sum() {

return x + y;

}

 

public bool IsBetween(int i) {

if ((x < i) && (i < y)) return true;

else return false;

}

 

public void Set(int a, int b) {

Console.Write("В методе Set(int, int). ");

x = a;

y = b;

Show();

}

Перегрузить.метод Set.

public void Set(double a, double b) {

Console.Write("В методе Set(double, double). ");

x = (int)a;

y = (int)b;

Show();

}

 

public void Show() {

Console.WriteLine("Значение x: {0}, значение у: {1}", x, y);

}

}

 

class AnotherClass {

string msg;

public AnotherClass(string str) {

msg = str;

}

public void Show() {

Console.WriteLine(msg);

}

}

class Demo {

static void Main() {

Console.WriteLine("Это заполнитель.");

}

}

 

Этот файл содержит класс MyClass, неоднократно использовавшийся в предыдущих примерах. Кроме того, в файл добавлены второй класс AnotherClass и третий класс Demo. Следовательно, сборка, полученная из исходного кода, находящегося в этом исходном файле, будет содержать три класса. Затем этот файл компилируется, и из него формируется исполняемый файл MyClasses.ехе. Именно эта сборка и будет опрашиваться программно.

Ниже приведена программа, в которой будут извлекаться сведения о файле сборки MyClasses.ехе. Ее исходный текст составляет содержимое второго файла.

 

/* Обнаружить сборку, определить типы и создать объект с помощью рефлексии. */

using System;

using System.Reflection;

class ReflectAssemblyDemo {

static void Main() {

int val;


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

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






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