Страница 260 из 502
<b>В методе Set(double, double). Значение х: 1, значение у: 23</b>
<b>Значение х: 1, значение у: 23</b>
А теперь рассмотрим порядок применения рефлексии для конструирования объекта класса MyClass. Сначала получается перечень открытых конструкторов в следующей строке кода.
<b>ConstructorInfo[] ci = t.GetConstructors();</b>
Затем для наглядности примера выводятся полученные конструкторы. После этого осуществляется поиск по списку конструктора, принимающего два аргумента, как показано в приведенном ниже фрагменте кода.
<b>for(x=0; х < 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("Конструирование класса MyClass(int). ");</b>
<b> x = y = i;</b>
<b> Show();</b>
<b> }</b>
<b> public MyClass(int i, int j) {</b>
<b> Console.WriteLine("Конструирование класса MyClass(int, int). ");</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>