Г. Шилдт - Полный справочник по C# (1160789), страница 84
Текст из файла (страница 84)
TypeКласс System.Туре —, "сердце" подсистемы отображения, поскольку он инкапсулирует тип. Он содержит множество свойств и методов, которые можно использоватьдля получения информации о типе во время выполнения программы. Класс Туре выведен из абстрактного класса System.Reflection.Memberlnfо.В классе Member Info определены следующие абстрактные свойства, которыепредназначены только для чтения:туре D e c i a n n g T y p eТип класса или интерфейса, в котором объявляется анализирузмый членMemberTypes MemberTypeТип членаs t r i n g NameИмя типаType ReflectedTypeТип отражаемого объектаОбратите внимание на то, что свойство MemberType имеет тип MemberTypes.Свойство MemberTypes представляет собой перечисление, которое определяет значения, соответствующие различным типам членов.
Среди прочих они включают следующие:MemberTypes.ConstructorvMemberTypes.MethodMemberTypes.FieldMemberTypes.EventMemberTypes.PropertyСледовательно, тип члена можно определить, опросив свойство MemberType. Например, если свойство MemberType содержит значение MemberTypes .Method, значит,интересующий нас член является методом.Класс Memberlnf о включает два абстрактных метода: GetCustomAttributes () иI sDefined (). Оба они связаны с атрибутами.К методам и свойствам, определенным в классе Memberlnf о, класс Туре добавляетнемало "своих".
Ниже перечислены наиболее часто используемые методы, определенные в классе Туре.454Часть I. Язык С#МетодНазначениеC o n s t r u c t o r i n f о [ ] G e t C o n s t r u c t o r s ()Получает список конструкторов для заданного типаE v e n t l n f о [ ] G e t E v e n t s ()Получает список событий для заданного типаF i e i d i n f о [ ] G e t F i e i d s ()Получает список полей для заданного типаM e m b e r i n f о [ ] GetMembers ()Получает список членов для заданного типаM e t h o d i n f о [ ] G e t M e t h o d s ()Получает список методов для заданного типаP r o p e r t y i n f о [ ] G e t P r o p e r t i e s ()Получает список свойств для заданного типаТеперь ознакомьтесь с наиболее часто используемыми свойствами, определеннымив классе Туре.СвойствоНазначениеAssembly AssemblyПолучает компоновочный файл для заданного типаTypeAttributesПолучает атрибуты для заданного типаAttributesт у р е BaseTypeПолучает непосредственный базовый тип для заданного типаs t r i n g FuliNameПолучает полное имя заданного типаbool isAbstractИстинно, если заданный тип является абстрактнымbool i sArrayИстинно, если заданный тип является массивомbool isClassИстинно, если заданный тип является классомb o o l isEnumИстинно, если заданный тип является перечислениемs t r i n g NamespaceПолучает пространство имен для заданного типаИспользование отраженияИспользуя методы и свойства класса Туре, во время выполнения программы можно получить подробную информацию о типе.
Это чрезвычайно мощное средство, поскольку, получив информацию о типе, можно вызвать конструкторы этого типа, егометоды и использовать его свойства. Таким образом, отражение позволяет использовать код, который недоступен в период компиляции программы.Программный интерфейс Reflection API —довольно обширная тема, и здесь невозможно рассмотреть ее в полном объеме. (Полное описание Reflection API — это материал для целой книги!) Но интерфейс Reflection API столь логичен, что, поняв, какиспользовать одну его часть, нетрудно разобраться во всем остальном. В следующихразделах описаны ключевые способы применения средства отражения: получение информации о методах, вызов методов, создание объектов и загрузка типов из компоновочных файлов.Получение информации о методахС помощью Type-объекта можно получить список методов, поддерживаемых заданным типом.
Для этого используется метод GetMethods (). Один из форматов еговызова таков:Methodinfо[] GetMethods()Глава 17. Динамическая идентификация типов, отражение и атрибуты455Метод GetMethods () возвращает массив объектов типа Methodlnf о, которые описывают методы, поддерживаемые вызывающим типом. Класс Methodlnf о определен впространстве имен System. Reflection.Класс Methodlnfo — производный от абстрактного класса MethodBase, который,в свою очередь, выведен из класса Memberlnfo.
Таким образом, программисту доступны свойства и методы, определенные во всех трех классах. Например, чтобы получить имя метода, используйте свойство Name. Особого внимания заслуживают двачлена класса Methodlnfo: ReturnType и GetParameters ().Свойство ReturnType, которое имеет тип Туре, позволяет получить тип значения,возвращаемого методом.Метод GetParameters () возвращает список параметров, связанных с методом.Формат его вызова таков:Parameterlnfo[] GetParameters()Информация о параметрах содержится в объекте класса Parameterlnfo. В классеParameterlnfo определено множество свойств и методов, которые используются дляописания параметров.
Из них стоит обратить внимание на следующие два: свойствоName, которое представляет собой строку, содержащую имя параметра, и свойствоParameterType, которое описывает тип параметра. Тип параметра инкапсулирован вобъекте класса Туре.Рассмотрим программу, в которой средство отражения используется для полученияметодов, поддерживаемых классом MyClass.
Для каждого метода программа отображает его имя и тип возвращаемого им значения, а также имя и тип всех параметров,которые может иметь тот или иной метод.// Анализ методов с помощью средства отражения.using System;using System.Reflection;class MyClass {int x;int y;public MyClass(int i, int j) {x = i;у = j;}public int sum() {return x+y;}public bool isBetween(int i) {if(x < i && i < y) return true;else return false;public void s e t ( i n t a, i n t b) {x = a;У = b;}public void set(double a, double b) {x = (int) a;у = (int) b;456Часть I.
Язык С#public void show() {Console.WriteLine(" x: {0}, y: {1}", x, y ) ;class ReflectDemo {public static void Main() {Type t = typeof(MyClass); // Получаем Type-объект,// представляющий MyClass.Console.WriteLine("Анализ методов, определенных в " + t.Name);Console.WriteLine();Console.WriteLine("Поддерживаемыеметоды:" ) ;Methodlnfo[] mi = t.GetMethods();// Отображаем методы, поддерживаемые классом MyClass.foreach(Methodinfо m in mi) {// Отображаем тип значения, возвращаемого методом,/ / и имя метода.Console.Write("" + m.ReturnType.Name +11" + m.Name + " (") ;// Отображаем параметры.'г~Parameterlnfo[] pi = m.GetParameters();for(int i=0; i < pi.Length; iConsole.Write(pi[i].ParameterType.Name +11" + pi[i] .Name) ;if(i+l < pi.Length) Console.Write(", " ) ;Console.WriteLine(")");Console.WriteLine();Результаты выполнения этой программы такие:Анализ методов, определенных в MyClassПоддерживаемые методы:Int32 G e t H a s h C o d e OBoolean Equals(ObjectStringobj)ToStringOInt32 sum()Boolean isBetween(Int32 i)Void set(Int32 a, Int32 b)Глава 17.
Динамическая идентификация типов, отражение и атрибуты457Void set(Double a, Double b)Void show()Type GetType()Обратите внимание на то, что помимо методов, определенных в классе MyClass,здесь также отображаются методы, определенные в классе o b j e c t . Дело в том, что всетипы в С# выведены из класса o b j e c t .
Также стоит отметить, что для имен типовздесь используются имена .NET-структуры. Обратите внимание еще на то, что методs e t () отображен дважды. Этому есть простое объяснение: метод s e t ( ) перегружен.Одна его версия принимает аргументы типа i n t , а вторая — аргументы типа double.Эта программа требует некоторых пояснений. Прежде всего, отметим, что в классеMyClass определяется public-конструктор и ряд public-методов, включая перегруженный метод s e t ().
При выполнении строки кода из метода Main () получаем объект класса Туре, представляющий класс MyClass:Type t = typeof(MyClass); // Получаем Type-объект,// представляющий MyClass.IИспользуя переменную t и интерфейс Reflection API, программа отображает информацию о методах, поддерживаемых классом MyClass. Сначала с помощью следующей инструкции получаем список методов:I MethodlnfoU mi = t . G e t M e t h o d s ( ) ;Затем выполняется цикл f oreach, на итерациях которого для каждого метода отображается тип возвращаемого им значения, имя метода и его параметры:// Отображаем тип значения, возвращаемого методом,/ / и имя метода.Console.Write(и" + m.ReturnType.Name +" " + m.Name + "(") ;// Отображаем параметры.Parameterlnf о [ ] pi =• m.GetParameters () ;for(int i=0; i < pi.Length; i++) {Console.Write(pi[i].ParameterType.Name +" " + pi[i].Name);if(i+l < pi.Length) Console.Write(", " ) ;}В этом фрагменте программы информация о параметрах каждого метода считывается посредством вызова метода GetParameters () и сохраняется в массиве p i .
Затемв цикле for выполняется опрос массива p i и отображается тип каждого параметра иего имя. Главное здесь то, что эта информация считывается динамически во времявыполнения программы, т.е. без предварительной информации о классе MyClass.Второй формат вызова метода GetMethods ()Второй формат вызова метода GetMethods () позволяет задать различные флаги,которые фильтруют возвращаемые методы. Этот формат таков:Methodlnfo[] GetMethods(BindingFlags flags)Эта версия получает только те методы, которые соответствуют заданному критерию. BindingFlags — это перечисление.
Ниже описаны наиболее употребительныеего значения:458Часть I. Язык С#ЗначениеDeciaredOnlyinstanceNonPublicPublicstaticОписаниеСчитывание только тех методов, которые определены в заданном классе. Унаследованныеметоды в результат не включаютсяСчитывание методов экземпляровСчитывание не-риЫю-методовСчитывание public-методовСчитывание static-методовДва или больше задаваемых флагов можно объединять с помощью оператора ИЛИ.С флагами P u b l i c или NonPublic необходимо устанавливать флаги I n s t a n c e илиS t a t i c . В противном случае метод GetMethods () не возвратит ни одного метода.Одно из основных применений BindingFlags-формата, используемого при вызове метода GetMethods ( ) , — получение списка определенных в классе методов, но безучета унаследованных.
Этот вариант особенно полезен в случае, когда нам не нужнаинформация о методах, определенных объектом. Попробуем, например, заменить вызов метода GetMethods () в предыдущей программе таким вариантом:// Тепеь получим только те методы, которые объявлены// в классе MyClass.Methodlnfo[] mi = t.GetMethods(BindingFlags.DeciaredOnly |BindingFlags.Instance |BindingFlags.Public) ;После внесения в профамму этого изменения получаем следующие результаты:Анализ методов, определенных в MyClassПоддерживаемые методы:Int32 sum()Boolean isBetween(Int32 i)Void set(Int32 a, Int32 b)Void set(Double a, Double b)Void show()Как видите, теперь отображены только те методы, которые явно определены вклассе MyClass.Вызов методов с помощью средства отраженияЗная, какие методы поддерживает тип, можно вызвать любой из них. Для этогоиспользуется метод Invoke О, который определен в классе Methodlnfo. Формат еговызова таков:object Inyoke(object ob, o b j e c t [ ] args)Здесь параметр ob — это ссылка на объект, для которого вызывается нужный метод.