Г. Шилдт - С#4.0 Полное руководство (1160795), страница 104
Текст из файла (страница 104)
В противном случае не будут извлечены сведения ни об одном из методов. Форма В1пс)1пор1аов метода Вебнесиос(в () чаще всего применяется для получения списка методов, определенных в классе, без дополнительного извлечения наследуемых методов. Это особенно удобно в тех случаях, когда требуется исключить получение сведений о методах, определяемых в классе конкретного объекта.
В качестве примера попробуем выполнить следующую замену в вызове метода ВебнеЬЬос)в () из предыдущей программы. 648 часть ). язык с)) Чо1О Яег(тпСЗг а, 1пСЗЗ Ь) Чоьс Яег(попЬ1е а, ОооЬ1е Ы чо1г) Яьои() Как видите, теперь выводятся только те методы, которые явно определены в классе МуС1аяя. Вызов методов с помощью рефлексии Как только методы, поддерживаемые определенным типом данных, становятся известны, их можно вызывать.
Для этой цели служит метод 1пчохе ( ), входящий в состав класса Меспог(1пго. Ниже приведена одна из форм этого метода: оЬЗесг 1пчоье(оЬЗесо оЬЗ, оЬЗесо() рагатесеге) где оьз обозначает ссылку на объект, для которого вызывается метод. Для вызова сгатических методов (Я са 11с) в качестве параметра оь 1' передается пустое значение (по 11).
Любые аргументы, которые должны быть переданы методу, указываются в массиве рагатеаегя. Если же аргументы не нужны, то вместо массива рагатеаегз указывается пустое значение (пп11). Кроме того, количество элементов массива рагащеаега должно точно соответствовать количеству передаваемых аргументов. Так, если требуется передать два аргумента, то массив ра гаме Гегя должен состоять из двух элементов, но не из трех или четырех. Значение, возвращаемое вызываемым методом, передается методу 1пчо)<е (), который и возвращает его.
Для вызова конкретного метода достаточно вызвать метод 1пчояе () для экземпляра объекта типа мегьог)1п1о, получаемого при вызове метода яесмесьоа)з () . Эта процедура демонстрируется в приведенном ниже примере программы. !/ Вызвать методы с помощью рефлексии. ов1по Яувсещг пагод яувоещ.ае11есаьоп; с1авв Нус1авв ( ьпс х; ьпс у; роЫгс Мус1авв(1пг 1, ьпо З) ( х у = 3' ) роЫгс гпс Яот() ( гесогп х+у; роЬ11с Ьоо1 1вВегиееп(ьпг 1) 11((х < 1) ьь (1 < у)) гегогп сгоег е1ве гегпгп Га1ве; Глава 17. Динамическая идентиФикация типов, рефвексия и атрибуты 549 роЬ1ьс чо1б Яев(ьпп а, тпп Ь) ( Сопяо1е.игтпе("В методе Яеп(тпп, 1пс).
") х= а; у = Ьт Яппи (]; О перегрузить метод Яег. рпЬ11с чо10 Бес(с(ооЬ1е а, бооЬ1е Ь) ( Сопво1е.игтсе("В методе Беп(с)ооЬ1е, оооЬ1е). "); х = (ьпг) а; у = (ьпс) Ь; Бпои (); ) роЬ11с чово Яппи() ( Сопво1е.игтсе11пе("Значение х: (0), значение у: ( 1)", х, у); ) с1аяя 1пчояемесЬОево ( всас1с чотб Мвтп() ( Туре Г = Суреот(мус1аяя)т МуС1авя ге11есГОЬ = пеи Мус1авв(10, 20); 1пг ча1; сопво1е.хг1пеьапе("Вызов методов, определенных в классе " ь г.хаве) Сопяо1е.иг1ге11пе()т Меснос)1пРо[) вт = Г.беГМеппобя(); // Вызвать каждый метод.
тогеасп(Меснобтпто в Тп вь) ( // Получить параметры. Рагавесег1пто[] рь = в.ОеГРагавепегя() 11(в.Хаме.соврагеТо("Яес")==О $6 р1[0].Рагавесегтуре == Гурео1(тпс)) ( оЬ]есс(] агдя = пеи оЬтесь(2]; агдя(О] = 9; агОя[1] = 18; в,1пчове(гет1есГОЬ, агся)) ) е1яе 11(в.наве.СоврагеТо("яес")==0 ВВ РТ(0].рагавепегТуре == Гуреот(бооЬ1е)) ( оЬ]есг[) агдя = пеи оЬ]вся[2]; алов[0] = 1.12; агдв(1) = 23.48 в.тпчоке(ге11есгОЬ, агдя)т ) е1ве 11(в.Хаме.соврагето("Яов")==0) ( ча1 = (Тпг) в.1пчо)ье(ге11есГОЬ, по11); Сопво1е.игтпеЬьпе("Сумма равна " + ча1); ) е1яе 11(в.Хаме.СоврагеТо("1яВесиееп")==О) ( 550 Часть!.
язык С() оЬзесс[] агчя = пен оЬ)есс[1]; агчя[0) = 141 гс((Ьоо1) в.гпчоке(геГ1есГОЬ, агдя)) сопяо1е.иггсесгпе("Значение 14 находится между х и у")г е1яе гс(в.неве.соврагето("Бпон")==0) ( в.1пчоке(геГ1есгОЬ, по11)г ) ) Вот к какому результату приводит выполнение этой программы. Вызов методов, определенных в классе МуС1аяя Сумма равна 30 Значение 14 находится между х и у В методе Бег(гпг, гпг). Значение х: 9, значение у: 18 В методе Бес(бооЬ1е, бооЬ|е).
Значение х: 1, значение у: 23 Значение х: 1, значение у: 23 Рассмотрим подробнее порядок вызова методов. Сначала создается список методов. Затем в цикле Тогеасп извлекаются сведения об их параметрах. Далее каждый метод вызывается с указанием соответствующего типа и числа аргументов в последовательном ряде условных операторов 1 г /е1 я е. Обратите особое внимание на перегрузку метода Бег () в приведенном ниже фрагменте кода.
гг(в.каме.СоврагеТо("Бег")==0 йй рг[0).рагавесегТуре == Суреас(1пс)) ( оЬзесг(] агдя = пен оЬ)есс[2]г агдя[0] = 91 агре[1] = 18; в.1пчоке(геГ1есСОЬ, агча)г ) е1яе гт(в.маме.соврагеТо("Бес")==0 йй рг[0).Рагавесегтуре == Гуреос(бооЬ1е)) ( опзесг[) агдя = пен оЬзесс[2]) агчя[0] = 1.121 агдя(1) = 23.41 в.гпчоке(геГ1еоГОЬ, аг9я)1 ) Если имя метода — Бес, то проверяется тип первого параметра, чтобы выявить конкретный вариант этого метода. Так, если это метод Бес (1пс, 1пс), то его аргументы загружаются в массив агоя.
В противном случае используются аргументы типа бопЬ1е. Получение конструкторов конкретного типа В предыдущем примере при вызове методов, определенных в классенуС1аяя, преимущества рефлексии не использовались, поскольку объект типа МуС1ая я создавался явным образом. В таком случае было бы намного проще вызвать для него методы обычным образом.
Но сильные стороны рефлексии проявляются наиболее заметно лишь в том случае, если объект создается динамически во время выполнения. И для Глава 11 Динамическая идентификации типов, рефлексия и атрибуты 551 этого необходимо получить сначала список конструкторов, а затем экземпляр объекта заданного типа, вызвав один из этих конструкторов. Такой механизм позволяет получать во время выполнения экземпляр объекта любого типа, даже не указывая его имя в операторе объявления. Конструкторы конкретного типа получаются при вызове метода СеЬСопясгпсгогя () для объекта класса Туре. Ниже приведена одна из наиболее часто используемых форм этого метода.
Сопясгпссог1пго() Сессопвсгпссогя() Метод СеЬСопясгпсгогя () возвращает массив объектов класса Сопясгпсгог1п1о, описывающих конструкторы. Класс Сопяггисгог1пго является производным от абстрактного класса МеСЬос)наяе, который в свою очередь наследует от класса МещЬег1пго. В нем также определен ряд собственных методов. К их числу относится интересующий нас метод сессопясгнссогя (), возвращающий список параметров, связанных с конструктором. Этот метод действует таким же образом, как и упоминавшийся ранее метод сесрагащесегя (), определенный в классе мегьос(1пго.
Как только будет обнаружен подходящий конструктор, для создания объекта вызывается метод 1пчохе (), определенный в классе сопясгпссог1пго. Ниже приведена одна из форм этого метода. ЬЬЗесс 1пчохе(оЬ)ест() рагаюесегя) Любые аргументы, которые требуется передать методу, указываются в массиве рагатегегя. Если же аргументы не нужны, то вместо массива рагащесегя указывается пустое значение (по11).
Но в любом случае количество элементов массива рагащегегя должно совпадать с количеством передаваемых аргументов, а типы аргументов — с типами параметров. Метод 1пчо)се () возвращает ссылку на сконструированный объект. В приведенном ниже примере программы рефлексия используется для создания экземпляра объекта класса Мус1ая я. Создать объект с помощью рефлексии. пяьпч Яуясещ; ия1по Яуясею.ке11есгьоп; с1аяя МуС1аяя ( лпг х; 1пс у; рнЬ11с МуС1аяя(апс 1) ( Сопяо1е.нг1сеъгпе (" Конструирование класса МуС1авя (Тпс, 1пс) . "); х = у = ) риЬ11с МуС1аяя(1пс 1, лпс )) ( Сопяо1е.нглсеъвпе("Конструирование класса МуС1аяв(ьпс, 1пг).
"); х = ).; у=)~ Бпон (); 552 Часть!. Язык С() рпЫгс 1пс Япщ() гегели х+у; ) рчЫ1с Ьоо1 1вВеснееп Сьпс г) ( 1Е((х < г) Яй (1 < у)) геспгп Сгче1 е1ве гегигп йа1ве) ) роЫгс чогя( Яео(1пг а, 1пс Ц ( Сопво1е.кггсе("В методе Яес(гпс, 1пв). "); х = а) У =Ь; Ялом (); // Перегрузить метод Яег. рпЬ11с чо1б Яег(г(оцЬ1е а, оочЪ1е Ь) ( Сопво1е.кг1яе("В методе(йоиЬ1е, оопЬ1е). "); х = ().пг) а; у = (1пг) Ь) Ялом (); ) риЬ11с чотг( ЯЬон() ( Сопяо1е.кггсеьгпе("Значение х: (О), значение у: (1)", х, у); ) ) с1авв 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е.кггсеЫпе()) Глава 17. Динамическая идентиФикация типов, реФлексия и атрибуты 553 // Найти подходящий конструктор.
Тпс х; Рог(х=О; х < сс.сепдСЛу х++) ( Рагавегвг1пто [] рл = сг [х! /ВеСРагавеСегв () 1Е(р1.сепдСЛ == 2) ЬгеаК; ) 11(х == с1.1епОКЛ) ( Сопяо1е.нг1ге11пе("Подходящий конструктор не найден."); гегогпу ) е1зе сопяо1е.нгусеьлпе("найден конструктор с двумя параметрами.1п") Сконструировать объект. оЬ]есс() сопзаг9в = пен оЬ]есс[2]; сопяагОя[О] = 10; сопвагОя[1) = 20) оь1есс гет1ессоь = сг[х].1пчоке(сопяагоз); Сопяо1е.иг1гесспе("КпВызов методов для объекта гет1есСОЬ.") Сопво1е.игТСевупе() ) Меглоб1пто[) в1 = С.ОеСМеСЛобз()4 Вызвать каждый метод.