Г. Шилдт - С#4.0 Полное руководство (1160795), страница 105
Текст из файла (страница 105)
ТогеасЛ(МеСЛоб1пто в гп вл) ( // Получить параметры. Рагавегег1пто[) рг = в.беСРагатегегв(); гт(т.нате.соврагето("Яег")==0 аа рл(0].рагатегегТуре == Суреот(лпг)) ( Зто метод ЯеС(лпг, 1пг). оЬ]есс[) аг9я = пен оЬ]есс[2)) аг9я[0) = 9; аг9я[1] = 1В; в.1пчоке(гет1ессОЬ, агдя)) ) е1ве 11(т.нате.соврагеТо("Яег")==О аа рл[0].рагатеСегтуре == Суреот(бовЬ1е)) Это метод Яег(боиЬ1е, боиЬ1е). оЬ]есс(] аг9в = пен оЬОесс[2]; агдя(0] = 1.12; агдя[1] = 23.4; в.1пчоке(гет1есСОЬ, агдя); ) е1ве РЕ(в.мате.СоврагеТо("Япв")==0) ( ча1 = (1пС) в.1пчоке(гет1есСОЬ, по11); Сопво1е.игссе01пе("Сумма равна " ь ча1)1 ) е1яе 11(в.нате.соврагето("1ввегнееп")==О) ( оЬ]есс(] агоя = пен оЬЗесс[1); агдя[0] = 14; 11((Ьоо1) в.1пчоке(гет1есСОЬ, аг9я)) Сопяо1е.иглгеввпе("Значение 14 находится между х и у") 554 Часть ]гйзык С№ е1яе 11(м.эаие.соиратето("Зпон")==0) ( и.1пчоке(те11естОЬ, пп11)г ) ) ) ) Эта программа дает следующий результат.
доступные конструкторы: МуС1азя(1пт32 т) Мусгаяя(гптэг ', гптЗг 3) Найден конструктор с двумя параметрами. Конструирование класса МуС1аяя(тпт, 1пт) Значение х: 10, значение у: 20 Вызов методов для объекта те11естОЬ Сумма равна 30 Значение 14 находится между х и у В методе Зет(1пт, Тпт). Значение х: 9, значение у: 16 В методе Нет(бопЫе, допЫе) . значение х: 1, значение у: 23 Значение х: 1, значение у: 23 А теперь рассмотрим порядок применения рефлексии для конструирования объекта класса МуС1аяя. Сначала получается перечень открытых конструкторов в следующей строке кода. сопяттпстот1псо[] ст = Ь.Оетсопяттпстотя() Затем для наглядности примера выводятся полученные конструкторы. После этого осуществляется поиск по списку конструктора, принимающего два аргумента, как показано в приведенном ниже фрагменте кода.
тот(х=О; х < ст.ьепчтьг х.ь+) ( Ратаиетет1псо[) рт = с1(х].Оетратаиететв() 11(р1.ьепчтп == 2) Ьтеа)гг ) Если такой конструктор найден, как в данном примере, то в следующем фрагменте кода получается экземпляр объекта заданного типа. // Сконструировать объект. оЬ]ест(] сопяатчв = пен оЬ]ест[2]1 сопяатчя(0) = 10; сопяатчя(1] = 20; оЬ]ест тет1естОЬ = сг[х].1пчоке(сопяатчя) После вызова метода 1пчо)ге () переменная экземпляра тейесССЬ будет ссылаться на объект типа мус1аяя. А далее в программе выполняются соответствующие методы для экземпляра этого объекта.
Следует, однако, иметь в виду, что ради простоты в данном примере предполагается наличие лишь одного конструктора с двумя аргументами типа Тпт. Очевидно, что в реальном коде придется дополнительно проверять соответствие типов каждого параметра и аргумента. Глава 1т.
Динамическая идентификация типов, рефлексия и атрибуты 555 Получение типов данных из сборок В предыдущем примере все сведения о классе МуС1аяя были получены с помощью рефлексии, за исключением одного элемента: типа самого класса МуС1аяя. Несмотря на то что сведения о классе получались в предыдущем примере динамически, этот пример опирался на тот факт, что имя типа МуС1ая я было известно заранее и использовалось в операторе Суре о Т для получения объекта класса Туре, по отношению к которому осуществлялось косвенное или непосредственное обращение к методам рефлексии.
В некоторых случаях такой подход может оказаться вполне пригодным, но истинные преимущества рефлексии проявляются лишь тогда, когда доступные в программе типы данных определяются динамически в результате анализа содержимого других сборок. Как следует из главы 16, сборка несет в себе сведения о типах классов, структур и прочих элементов данных, которые в ней содержатся. Прикладной интерфейс Еейесбоп АР! позволяет загрузить сборку, извлечь сведения о ней и получить экземпляры объектов любых открыто доступных в ней типов. Используя этот механизм, программа может выявлять свою среду и использовать те функциональные возможности, которые могут оказаться доступными без явного их определения во время компиляции.
Это очень эффективный и привлекательный принцип. Представьте себе, например, программу, которая выполняет роль "браузера типов", отображая типы данных, доступные в системе, или же инструментальное средство разработки, позволяющее визуально составлять программы из различных типов данных, поддерживаемых в системе. А поскольку все сведения о типах могут быть извлечены и проверены, то ограничений на применение рефлексии практически не существует. Для получения сведений о сборке сначала необходимо создать объект класса ляяещЬ1у. В классе дяяетЬ1у открытый конструктор не определяется.
Вместо этого объект класса дяяещЬ1у получается в результате вызова одного из его методов. Так, для загрузки сборки по заданному ее имени служит метод Ьоас(ргощ ( ) . Ниже приведена его соответствующая форма: атас!с Ляяещьту Ьсябггсщ (яггтпс файл сборки) где файл сбсркиобозначает конкретное имя файла сборки. Как только будет получен объект класса ля яещЬ1у, появится возможность обнаружить определенные в нем типы данных, вызвав для него метод Сегтурея () в приведенной ниже общей форме. Туре() Яептурея() Этот метод возвращает массив типов, содержащихся в сборке.
Для того чтобы продемонстрировать порядок обнаружения типов в сборке, потребуются два исходных файла. Первый файл будет содержать ряд классов, обнаруживаемых в коде из второго файла. Создадим сначала файл МуС1а я я ее . ся, содержащий следующий код. Файл, содержащий три класса и носящий имя Мус1аяяея.ся. па!по Яуягещ; с1аяя Мус1аяя ( Тпс х; тпс у; Глава 17. Динамическая идентификация типов, рефлексия и атрибуты 557 с1авя Оещо ( ягагус чогб Масп() ( Сопяо1е.иг1Сеььпе("Это заполнитель.") ) ) Зтот файл содержит класс МуС1аяз, неоднократно использовавшийся в предыдущих примерах.
Кроме того, в файл добавлены второй класс Апог]тегС1аяя и третий класс Оещо. Следовательно, сборка, полученная из исходного кода, находящегося в этом исходном файле, будет содержать три класса. Затем этот файл компилируется, и из него формируется исполняемый файл МуС1аяя ее . ехе. Именно эта сборка и будет опрашиваться программно. Ниже приведена программа, в которой будут извлекаться сведения о файле сборки МуС1аяяея. ехе. Ее исходный текст составляет содержимое второго файла.
/* Обнаружить сборку, определить типы и создать объект с помощью рефлексии. */ ияупо Буясещ; пв1пс Яуяяещ.не11есСЬоп; с1аяя Яег1есгляяещб1уОещо ( ягаг1с чоье Мауп() ( 1пс ча1; // Загрузить сборку МуС1аяяея.ехе. АяяещЬ1у аящ = Аяяещ)з1у.Ьоабргощ("Мус1авяея.ехе")," // Обнаружить типы, содержащиеся в сборке МуС1аяяея.ехе. туре[] а11Сурея = аящ.оегтурея(); Тогеасб(туре Сещр 1п а11гурея) Сопяо1е.иг1СеЬ1пе("Найдено: " + Сещр.иаще); Сопво1е.Хгугеввпе() // Использовать первый тип, в данном случае — класс МуС1аяя.
Туре С = а11сурея[0]у // использовать первый найденный класс Сопяо1е.иглсеЬ1пе("Использовано: " + С.Нане); // Получить сведения о конструкторе. СопяСгисгог1пго[] су = С.оеССопяггпсгогя() Сопяо1е.игтгевьпе(ГДоступные конструкторы: ") Тогеаск(сопяггссгогтпто с Ьп су) ( Вывести возвращаемый тип и имя. Сопяо1е.иггге(" " + С.Хазе + "("); Вывести параметры. Рагащеяег1пго[] р1 = с.оеСРагащегегя(); Тот(1пС с=О; 1 < рь.Ьепцг)П 1+т) ( сопяо1е.хглсе(рл[1).рагащесегтуре.нане + " " + р1[1).хане)у ЬГ(я+1 < РЬ.ЬепЗСН) Сопао1е.Хг1ге(", "); ) 558 Часть [. Язык С№ Сопяо1е.нг1Геь1пе(")") ) Сопяо1е.Иггяеььпе()т // Найти подходящий конструктор.
1пг х; Рог(х=О) х < сг.ьепдГЬ) х++) ( Рагаветег1пто() р1 = с1(х) .ЯеГРагавеяегя (); 11(рг.ьепдяь == 2) Ьгеа)ст ] 11(х == сг.ьепдГЬ) Сопяо1е.кг1яе11пе("Подходящий конструктор не найден."); гегпгп; ) е1яе Сопяо1е .Иг1яе11пе (" Найден конструктор с двумя параметрами. 1п"); // Сконструировать объект. оЬ]еся(] сопяагдя = пен оЬ1еся[2); сопяагдя[0) = 10; сопяагдя(1] = 20; оЬ]ест ге11есГОЪ = с1[х].
1пчохе(сопяагдя)т сопяо1е.иг1се11пе("1пВызоа методов для объекта ге11есгбь.") Сопяо1е.Иггсеьгпе()т Мескос)1пто[] вг = Г.деСМеяьобя()т // Вызвать каждый метод. Тягаясь(Медьоб1пто в гп вг) ( // Получить параметры. Рагавесег1пто[) рг = в.деСРагавесегя() 11(В.ИаВЕ.СОВраГЕТО("ЯЕГь)==0 яа рг[0).РагавесегТуре == Гуреос(зпс)) ( // Это метод Яея(зпя, 1пя). оЬ1есг[) агдя = пен оЬ]ест[2); агдя[0] = Эт агдя[1] = 18) в.1пчоке(геГ1есгОь, агдя)т ) е1яе 11(в.каме.СоврагеТо("Яес")==0 ьь р1[0].РагавесегТуре == ГуреоТ(с)ооЬ1е)) ( Это метод Яес(г(опЬ1е, с)опЬ1е). оЬ]ест[] агдя = пен оЬ]ест[2)) агдя(0] = 1.12; агдя(1) = 23.4т в.1пчоье(ге11есСОЬ, агдя); ) е1яе 11(в.каме.соврагеТо("Япв")==0) ( ча1 " (1пс) в.1пчоье(ге11есГОЬ, пп11); Сопяо1е.кг1се11пе("Сумма равна " + ча1)т ) е1яе гт(в.Маме.соврагеТо("1яВеьнееп")==0) ( оЬЭеся(] агдя = пен оЬЭесс[1); Глава 17. Динамическая идентификация типов, рефлексия и атрибуты 559 агав(0) = 14; ТГ((Ьоо1) щ.1пчоке(гет1есГОЬ, агяв) ) Сопво1е.нгьсеъьпе("Значение 14 находится между х и у") ) е1ве 113щ.