Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 102
Текст из файла (страница 102)
Но как минимум флажок 1лякапсе или Вгагус следует указывать вместе с флажком РоЫ1с или МопроЫ1с, В противном случае не будут извлечены сведения ни об одном из методов. Форма В1пбупду1адя метода Оегиег)тот)я () чаще всего применяется для получения списка методов, определенных в классе, без дополнительного извлечения наследуемых методов.
Это особенно удобно в тех случаях, когда требуется исключить получение сведений о методах, определяемых в классе конкретного объекта. В качестве примера попробуем произвести следующую замену в вызове метода Оекиег)тот)я () из предыдущей программы; // Теперь получаютсл сведЕния только о тех методах, О которые объявлены в классе Муотаяя. Мекнобтлто() и1 - С.аеСМесвобя( Вапб1лцгтадя.пес1агебол1у ) В1лб1пцг1адя.1лягалсе Валб1пцгтадя.риЫас); После этой замены программа дает следующий результат: Анализ методов, определенных в классе МуС1аяя Поддерживаемые методы: тпгзг 31 И Воо1еап тявегнееп(1лг32 1) уо1б Бег(1п132 а, 1лг32 Ы Чо1б Бег(роиЫе а, СоиЫе Ы Но16 Явок() Как видите, теперь выводятся только те методы, которые явно определены в классе МУС1аяя. Вторая форма метода (яееяае огзойа 0 Существует вторая форма метода Оекиег)тот)я (), позволяющая указывать различные флажки для отфильтровывания извлекаемых сведений о методах.
Ниже приведена эта общая форма метода месмес)тес)я () . метноб1лго() Оесмеснобя(Вулбглцг1адя флажки) 530 Часть(. Язык С№ Вызов методов с помощью рефлексии Как только методы, поддерживаемые определенным типом данных, становятся известны, их можно вызывать. Для этой цели служит метод 1пуохе (), входящий в состав класса Мегнот(1п№о. Ниже приведена одна из форм этого метода.
оЬ)есс 1дгоке(оЬ)есс оЬ, оь)есс() агдя) где оь обозначает ссылку на объект, для которого вызывается метод. Для вызова статических методов (яьас го) в качестве параметра оь передается пустое значение (пп11). Любые аргументы, которые должны быть переданы методу, указываются в массиве агдэ. Если же аргументы не нужны, то в качестве параметра агдэ указывается пустое значение (пи11). Кроме того, количество элементов массива агдэ должно точно соответствовать количеству передаваемых аргументов. Так, если требуется передать два аргумента, то массив агдя должен состоять из двух элементов, но не из трех или четырех.
Значение, возврзтцаемое вызываемым методом, передается методу 1птто)се (), который и возвращает его. Для вызова конкретного метода достаточно вызвать метод 1пуохе () для экземпляра объекта типа Мегьог(1п1о, получаемого при вызове метода Сесмесьог(я () .
Эта процедура демонстрируется в приведенном ниже примере программы. // Вызвать методы с помощьв рефлексии. ия1пд Буясекп иягод Буясещ.ке11ессгоо) с1аяя МуС1аяя ( 1ос х) 1пс у) риЫ1с МуС1аяя(гос г, гьс 3) ( х=).т у = )т риЫ1с 1ог Вищ() ( гегигп х+у) риЬ11о Ьоо1 1янесиееп(1ос 1) ( 11((х < г) яя (1 < у)) гегигд ггяет е1яе гегигд Га1яе) ) риЫ1с ко1т( Бес(гпс а, 1пс Ы ( Содяо1е.ыггсе("В методе Бес(гос, гас). ")) х = ат у=Ь! знои () т // Перегрузить метод Бес. риы1с го1к) Бег(к)оиые а, ооыЫе Ы ( Глава )7.
Динамическая идентификация типов, рефлексия и атрибуты 531 Сопяо1е.Игкге("В методе Яес(т(оиЬ1е, т)опЬ1е). ")т х = ().пк) ат у = (1пс) Ь) БЬои() ) ) рпЬ11с чокб ЯЬон() ( Сопво1е.нг1седапе("Значение х: (0), значение у: (1)", х, у)т ) ) с1аяв 1пчоиеМеГЬОево ( ясаскс чокс Мако() ( туре г = гуреок(мус1авв)т МуС1авв гег1есГОЬ пен МуС1авв(10, 20)т ).пс ча1т Сопво1е.нгккеЬкпе("Вызов методов, определенных в классе " + г.Нане) Сопяо1е.игксеЬТпе()) Мекпос(1пго(] вк Г.беГМеспот(в()) // Вызвать каждый метод. Когеасп(Меспос)1пко в 1п вк) ( // Получить параметры.
Рагавегегтпко[] р1 = в.беграгавегегя() ке(в.ыаве.соврагето("яег")= 0 ак рк[0].рагавесегТуре == Гуреок(кпс)) ( оь]есг [] агдя = пен оь]есг (2) т агдя[0] = 9( атея[1] = 18т в.1пчоие(гег1есГОЬ, агдя) т е1яе 11(в.нане.соврагето("Бег")==0 ка р1[0).рагавекегТуре = Гуреок(бочыае)) ( оЬ]еск[] агдя " пен оЬОесс[2)т агдв[0] = 1.12) ахея[1) = 23.4) в. 1пчоае (ге11есГОЬ, агдя) т ) е1ве 11(в.ыаве.соврагеТо("Яовх)==0) ( ча1 = (кпк) в.1пчоие(гек1есГОЬ, пп11)т Сопво1е.игккеЬкпе("Сумма равна " + ча1)т ) е1яе 11(в.нане.СоврагеТо("тяВекиееп")= 0) ( оь]есг[] агдв - пен оь)вся[1]т авда[0) = 14) ТК((Ьоо1) в.тпчоие(гег1есГОЬ, агдв]) Сопяо1е.ИгкгеЬ1пе("Значение 14 находится между х и у")т ) е1ве 11 (в.наве.соврагеТо ( хБЬоих) ==0) ( в.1пчоие(гек1есГОЬ, пп11)) ) 532 Часть ].
Язык С» Вот к какому результату приводит выполнение этой программы: Вызов методов, определенных в классе МуС1аяя Сумма равна 30 Значение 14 находится между х и у В методе Зек(1пС, Тпк). Значение хт 9, значение ут 18 В методе Зек(оочЬ1е, с)оиЬ1е). Значение х: 1, значение у: 23 Значение хт 1, значение у: 23 Рассмотрим подробнее порядок вызова методов. Сначала получается список методов. Затем в цикле гогеасп извлекаются сведения об их параметрах. Далее каждый метод вызывается с указанием соответствующего типа и числа аргументов в последовательном ряде условных операторов 1г !е1яе.
Обратите особое внимание на перегрузку метода зеС () в приведенном ниже фрагменте кода. ьг(в.паве.соврагето("зес")==0 аа ръ[0].РагавееегТуре == Суреос(ъпк)) ( оЬ3есС[] агдя = пен ОЬ]есС[2]) агдя[0] = 94 агдя[1] - 18) в.1пчохе(кег1ессоь, агдя)т ) е1яе 11(в.паве.соврагето("зес")==0 ая ръ[0].рагавекегТуре == Суреот(с)опЬ1е)) ( оЬ]есС[] агдя пен оЬ)есС[2]т агдя[0) 1.12) авда[1] = 23.4) в.1пчоке(гег1есСОЬ, агдя); Если метод имеет имя зес, то проверяется тип первого параметра, чтобы выявить конкретный вариант этого метода.
Так, если это метод ЗеС (ТпС, Тпг), то его аргументы загружаются в массив агдя. В противном случае используются аргументы типа к]опЬ1е. Получение конструкторов конкретного типа В предыдущем примере при вызове методов, определенных в классе МуС1аяя, преимущества рефлексии не использовались, поскольку объект типа муС1аяя создавался явным образом.
В таком случае было бы намного проще вызвать для него методы обычным образом. Но сильные стороны рефлексии проявляются наиболее заметно лишь в том случае, если объект создается динамически во время выполнения. И для этого необходимо получить сначала список конструкторов, а затем экземпляр объекта заданного типа, вызвав один из этих конструкторов. Такой механизм позволяет получить во время выполнения экземпляр объекта любого типа, даже не указывая его имя в операторе объявления. Конструкторы конкретного типа получаются при вызове метода беССопяСгпсСогя () для объекта класса туре.
Ниже приведена одна из наиболее употребительных форм этого метода. Сопякгоског1псо[) Пеесопякгпскогя() Глава!7. Динамическая идентификация типов, рефлексия и атрибуты 533 Метод СеССопякгистогя () возвращает массив объектов класса СопяггисСог1пбо, описывающих конструкторы. Класс сопясгиссог1пбо является производным от абстрактного класса месьос(Ваяв, который в свою очередь наследует от класса МевЬег1п го. В нем также определен ряд собственных методов.
К их числу относится интересующий нас метод сессопясгиссогя (), возвращающий список параметров, связанных с конструктором. Этот метод действует таким же образом, как и упоминавшийся ранее метод Яесрагавесегя (), определенный в классе МеСЬос(1пбо. Как только будет обнаружен подходящий конструктор, для создания объекта вызывается метод 1пиоке (), определенный в классе СопяСгиског1пбо. Ниже приведена одна из форм этого метода. оЬ)есС 1птоие(оЬ)есС [] агдя) Любые аргументы, которые требуется передать методу, указываются в массиве агдя. Если же аргументы не нужны, то в качестве параметра агдя указывается пустое значение (пи11). Но в любом случае количество элементов массива агдя должно совпадать с количеством передаваемых аргументов, а типы аргументов — с типами параметров.
Метод 1пиохе () возвращает ссылку на сконструированный объект. В приведенном ниже примере программы рефлексия используется для создания экземпляра объекта класса МуС1аяя. // Созвать объект с помощью ретлексии. ияапд Яуякевт иягпд Яуякев.аек1есС1опт с1аяя, МуС1аяя ( кпк хт кпс ут риЫ1с МуС1аяя(апС 1) ( Сопяо1е .Иггкеъапе ("Конструирование класса МуС1аяя (1пС, 1пС) . " ); х = у = 1) ) риЫас МуС1аяя(1пС 1, 1пС б) ( сопяо1е .Иг1сет апе ("конструирование класса мус1аяя (кпс, япс) . ") т х = 1т у=]) ЯЬон()т риЫ1с гпС Яив() ( гекигп х+у) ) риЬ11с Ьоо1 гянекнееп(1пС 1) ( 11((х < 1) кя (1 с у)) гесигп сгиет е1яе гесигп Га1яет 634 часть (. язык С» рчЫ1с коко Вес(ьпс а, Епс Ы ( СОПЗО1Е.ИГГСЕ(ЯВ МвтОдв ВЕС(ГПС, ЕПС) . ч) т х = а) у = Ьт ЯЬон (); // Перегрузить метод Яег. рчЬ1гс чо]к( Яег (к(очЫе а, к(опЫе Ь) ( Сопзо1е.Иг1Се (" Внутри метода(к(очЫе, бочЫе) . ") х = (гпс) а) у = [Епг) Ьт ЯЬон() ) ) риЫЕс чоск) ЯЬои() ( сопзо1е.иг) се1) пе (" Значение х: (0), значение у: (1) ", х, у); ) с1азз 1пчо)кесопзрещо ( зсас1с чо1к( маса() ( туре с = суреое(ыуС1азз)т 1пг ча11 // Получить сведения о конструкторе.
Сопзггчсгог1пЕо(] с1 = С.бегсопзггчсгогз() Сопзо1е.нг1СеЬЕпе(нйоступные конструкторы: ")т Еогеасп(сопзггпсгог1пЕо с 1п са) ( // Вывести возвращаемый тип и имя. сопзо1е.иг1се(" " + с.наще + "(")т // Вывести параметры. Рагащегег1пЕо() р1 = с.беСРагащегегз() Еог(апс 1=0) 1 < р1.ЬепЯСЬ) 1++) ( Сопяо1е.ыг1Се(рь(г].РагащегегТуре.ыаще + " Ь р).().].Иаще)т гй(1+1 < р1.ЬепдСЬ) Сопяо1е.ыг1Се(", ")т Сопзо1е.ыгаге)1пе(")я)) ) Сопзо1е.ыгЕСеЬЕпе()т // Найти подходящий конструктор. Епг х) Еог(х=ст х < с1.ЬепдСЬ; х++) ( РагащеСег1пЕо(] ра = с1[х].ЯеСРагащегегз() га(РЕ.ЬепдСЬ = 2) Ьгеа)ст Глава (7.
Динамическая идентификация типов, рефлексия и атрибуты 636 ьк(х == с1.ЬЕпдСЬ) ( Сопяо1е.игкгеЬЕпе("Подходящий конструктор не найден.")к гесигпт е1ве Сопво1е.ыг1геЬЕпе("Найден конструктор с двумя параметрами.1п") // СконстрУировать объект. оьбесс[] сопвагдв = пеи оьбесс[2]т сопвагдв[0] = 10т сопвагдв[1) = 204 оЬ]есс геЕ1ессОЬ са [х! .
1пчосе (сопвагдв) т сопво1е.хгксеькпе("тпВывов методов для объекта гее1ессбь.")т Сопяо1е .Хг1геЬ1пе () ) Мегпоб1пко[] вк = С.деСМегпобв()) // Выввать каждый метод. Еогеасп(Мегпоб1пЕо в 1п В1) ( // Получить параметры. Рагавегег1пко[! Р1 в.деСРагавегегв М т 1Е(в.ыаве.СоврагеТо("Яег")="0 ая ра[0!.РагавегегТуре Суреок(апг)) ( // Зто метод Яег(кпг, 1пг) . оьбесс[] агдв = пен оьбесс[2]т авда[0] = 94 авда[1) = 184 в.1пчохе(геЕ1есСОЬ, агдв)т ) е1яе ЕЕ(в.хаве.соврагето("Яес") =0 кк р1[0].Рагавегегтуре == Суреок(бопмке)) ( // Зто метод Яег (боиЬ1е, боиЬ1е) . оь]есс(! агдя = пен оьбесс[2]т агдв[0] = 1.124 авда[1) = 23.44 в.
1пчоке (гее1ессбь, агдя) т ) е1яе 1Е(в.ыаве.СоврагеТо("Япв")==0) ( ча1 (1пг) в. 1пчосе (геЕ1есСОЬ, пп11) ) Сопво1е.иг1геЬЕпе("Сумма равна " ь ча1)т ) е1яе 1Е(в.Хане.СоврагеТо("1вВегкееп")==0) ( оьбесс[] агдв = пеи оьбесс[1]т агдв[0] = 14) 1Е((Ьоо1) в.1пчосе(геЕ1есСОЬ, агдя)) Сопяо1е.ыгкгеЬЕпе( "Значение 14 находится между х и у")т е1яе 1Е(в.ыаве.СоврагеТо("ЯЬои")==0) ( в. 1пчохе(геЕ1есСОЬ, пп11)) ) 536 Часть (. Язык С() Эта программа дает следующий результат: доступные конструкторы: Мус1авв(гпезг ц Мус1азя(1пе32 1, 1пе32 3) Найден конструктор с двумя параметрами.