Язык программирования C#9 и платформа .NET5
// Получить информацию о типе с применением экземпляра SportsCar.SportsCar sc = new SportsCar();Type t = sc.GetType();Очевидно, что такой подход будет работать, только если подвергаемый рефлексии тип (
в данном случае) известен на этапе компиляции и в памяти присутствует его экземпляр. С учетом этого ограничения должно быть понятно, почему инструменты вродеSportsCarне получают информацию о типе, непосредственно вызывая методildasm.exeдля каждого типа — ведь утилитаSystem.Object.GetType()не компилировалась вместе с вашими специальными сборками.ildasm.exeПолучение информации о типе с помощью typeof()
Следующий способ получения информации о типе предполагает применение операции
:typeof// Получить информацию о типе с использованием операции typeof.Type t = typeof(SportsCar);В отличие от метода
операцияSystem.Object.GetType()удобна тем, что она не требует предварительного создания экземпляра объекта перед получением информации о типе. Однако кодовой базе по-прежнему должно быть известно об исследуемом типе на этапе компиляции, посколькуtypeofожидает получения строго типизированного имени типа.typeofПолучение информации о типе с помощью System.Туре.GetType()
Для получения информации о типе в более гибкой манере можно вызывать статический метод
классаGetType()и указывать полностью заданное строковое имя типа, который планируется изучить. При таком подходе знать тип, из которого будут извлекаться метаданные, на этапе компиляции не нужно, т.к. методSystem.Турепринимает в качестве параметра экземпляр вездесущего классаType.GetType().System.StringНа заметку! Когда речь идет о том, что при вызове метода
знание типа на этапе компиляции не требуется, имеется в виду тот факт, что данный метод может принимать любое строковое значение (а не строго типизированную переменную). Разумеется, знать имя типа в строковом формате по-прежнему необходимо!Туре.GetType()Метод
перегружен, позволяя указывать два булевских параметра, из которых один управляет тем, должно ли генерироваться исключение, если тип не удается найти, а второй отвечает за то, должен ли учитываться регистр символов в строке. В целях иллюстрации рассмотрим следующий код:Туре.GetType()// Получить информацию о типе с использованием статического// метода Туре.GetType().<b>// (Не генерировать исключение, если тип SportsCar не удается найти,</b><b>// и игнорировать регистр символов.)</b>Type t = Type.GetType("CarLibrary.SportsCar", false, true);В приведенном выше примере обратите внимание на то, что в строке, передаваемой методу
, никак не упоминается сборка, внутри которой содержится интересующий тип. В этом случае делается предположение о том, что тип определен внутри сборки, выполняющейся в текущий момент. Тем не менее, когда необходимо получить метаданные для типа из внешней сборки, строковый параметр форматируется с использованием полностью заданного имени типа, за которым следует запятая и дружественное имя сборки (имя сборки без информации о версии), содержащей интересующий тип:GetType()// Получить информацию о типе из внешней сборки.Type t = Type.GetType("CarLibrary.SportsCar, CarLibrary");Кроме того, в передаваемой методу
строке может быть указан символ "плюс" (GetType()) для обозначения вложенного типа. Пусть необходимо получить информацию о типе перечисления (+), вложенного в класс по имениSpyOptions. В таком случае можно написать следующий код:JamesBondCar// Получить информацию о типе для вложенного перечисления// внутри текущей сборки.Type t = Type.GetType("CarLibrary.JamesBondCar+SpyOptions");Построение специального средства для просмотра метаданных
Чтобы ознакомиться с базовым процессом рефлексии (и выяснить полезность класса
), создайте новый проект консольного приложения по имениSystem.Туре. Приложение будет отображать детали методов, свойств, полей и поддерживаемых интерфейсов (в дополнение к другим интересным данным) для любого типа внутриMyTypeViewer(вспомните, что все приложения .NET Core автоматически получают доступ к этой основной библиотеке классов платформы) или типа внутри самого приложенияSystem.Runtime.dll. После создания приложения не забудьте импортировать пространства именMyTypeViewer,SystemиSystem.Reflection:System.Linq// Эти пространства имен должны импортироваться для выполнения// любой рефлексии!using System;using System.Linq;using System.Reflection;Рефлексия методов
В класс
будут добавлены статические методы, каждый из которых принимает единственный параметрProgramи возвращаетSystem.Туре. Первым делом определите методvoid, который выводит имена методов, определенных во входном типе. Обратите внимание, чтоListMethods()возвращает массив объектовТуре.GetMethods(), по которому можно осуществлять проход с помощью стандартного циклаSystem.Reflection.MethodInfo:foreach// Отобразить имена методов в типе.static void ListMethods(Type t)