Добавить в цитаты Настройки чтения

Страница 260 из 502

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

<b>Значение х: 1, значение у: 23</b>

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

<b>ConstructorInfo[] ci = t.GetConstructors();</b>

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

<b>for(x=0; х &lt; ci.Length; х++)    {</b>

<b>  ParameterInfo[] pi = ci[x].GetParameters();</b>

<b>  if(pi.Length == 2) break;</b>

<b>}</b>

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

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

<b>object[] consargs = new object[2];</b>

<b>consargs[0] = 10;</b>

<b>consargs[1] = 20;</b>

<b>object reflectOb = ci[x].Invoke(consargs);</b>

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

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

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

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

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

<b>static Assembly LoadFrom(string файл_сборки)</b>

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

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

<b>Туре [] GetTypes()</b>

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

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

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

<b>using System;</b>

<b>class MyClass {</b>

<b>  int x;</b>

<b>  int y;</b>

<b>  public MyClass(int i) {</b>

<b>    Console.WriteLine(&quot;Конструирование класса MyClass(int). &quot;);</b>

<b>    x = y = i;</b>

<b>    Show();</b>

<b>  }</b>

<b>  public MyClass(int i, int j) {</b>

<b>    Console.WriteLine(&quot;Конструирование класса MyClass(int, int). &quot;);</b>

<b>    x = i;</b>

<b>    y = j;</b>

<b>    Show();</b>

<b>  }</b>

<b>  public int Sum() {</b>

<b>    return x + y;</b>

<b>  }</b>

<b>  public bool IsBetween(int i) {</b>