Поделиться через


Общие сведения об отражении и универсальные шаблоны

Обновлен: Ноябрь 2007

Есть два ключевых момента, позволяющих понять, как в отражении обрабатываются универсальные типы и методы:

  • Параметры типов для определений универсальных типов и определений универсальных методов представлены экземплярами класса Type.

    ms172334.alert_note(ru-ru,VS.90).gifПримечание.

    Поведение многих типов и методов класса Type отличается, если объект Type представляет параметр универсального типа. Эти различия документируются в темах, посвященных конкретным свойствам и методам. Примеры см. в разделах IsAutoClass и DeclaringType. В дополнение к этому некоторые члены являются допустимыми только в том случае, если объект Type представляет параметр универсального типа. Например, см. GetGenericTypeDefinition.

  • Если экземпляр класса Type представляет универсальный тип, он содержит массив типов, которые представляют параметры типа (для определений универсальных типов) или аргументы типов (для сконструированных типов). Это также справедливо для экземпляра класса MethodInfo, который представляет универсальный метод.

Отражение содержит методы классов Type и MethodInfo, которые позволяют получить доступ к массиву параметров типа и определить, представляет ли экземпляр класса Type параметр типа или фактический тип.

Пример, в котором демонстрируются рассматриваемые здесь методы, см. в разделе Практическое руководство. Изучение универсальных типов и создание их экземпляров при помощи отражения.

В следующем ниже обсуждении предполагается определенное знакомство с терминологией универсальных шаблонов, например знание того, в чем состоит отличие между параметрами типа и аргументами типа, а также открытыми и закрытыми сконструированными типами. Дополнительные сведения см. в разделе Общие сведения об универсальных шаблонах в .NET Framework.

Универсальный тип или универсальный метод

При использовании отражения для изучения неизвестного типа, представленного экземпляром класса Type, следует использовать свойство IsGenericType, которое позволяет определить, является ли неизвестный тип универсальным. Если тип является универсальным, это свойство возвращает значение true. Аналогичным образом при изучении неизвестного метода, представленного экземпляром класса MethodInfo, для определения того, является ли этот метод универсальным, следует использовать свойство IsGenericMethod.

Наличие определения универсального типа или метода

Свойство IsGenericTypeDefinition используется для определения того, представляет ли объект Type определение универсального типа, а метод IsGenericMethodDefinition — для определения того, представляет ли объект MethodInfo определение универсального метода.

Определения универсальных типов и методов являются шаблонами, на основе которых создаются типы, поддерживающие создание экземпляров. Универсальные типы в библиотеке классов .NET Framework, например Dictionary<TKey, TValue>, являются определениями универсальных типов.

Каким является тип или метод — открытым или закрытым

Универсальный тип или метод является закрытым, если все его параметры типа были заменены типами, в том числе все параметры типа для всех инкапсулирующих типов, были заменены типами, допускающими создание экземпляра. Если универсальный тип является закрытым, допускается только создание экземпляра на его основе. Если тип является открытым, свойство Type.ContainsGenericParameters возвращает значение true. Для методов та же самая функция выполняется методом MethodInfo.ContainsGenericParameters.

Создание закрытых универсальных типов

После получения определения универсального типа или метода следует при помощи метода MakeGenericType создать закрытый универсальный тип либо при помощи метода MakeGenericMethod – объект MethodInfo для закрытого универсального метода.

Получение определения универсального типа или метода

При наличии открытого универсального типа или метода, который не является определением универсального типа или метода нельзя создавать экземпляры такого типа или метода, а также указывать отсутствующие параметры типа. Необходимо иметь определение универсального типа или метода. Для получения определения универсального типа или метода GetGenericMethodDefinition используется метод GetGenericTypeDefinition.

Например, если при наличии объекта Type, представляющего тип Dictionary<int, string> (Dictionary(Of Integer, String) в Visual Basic) нужно создать тип Dictionary<string, MyClass>, можно при помощи метода GetGenericTypeDefinition получить объект Type, представляющий тип Dictionary<TKey, TValue>, а затем воспользоваться методом MakeGenericType для создания объекта Type, представляющий тип Dictionary<int, MyClass>.

Пример открытого универсального типа, который не является универсальным типом, см. в разделе "Параметр типа или аргумент типа" ниже в этой теме.

Изучение аргументов типа и параметров типа

Для получения массива объектов Type, которые представляют параметры типа или аргументы типа для универсального типа, следует воспользоваться методом Type.GetGenericArguments, а для выполнения тех же действий в отношении универсального метода — методом MethodInfo.GetGenericArguments.

Если станет понятно, что объект Type представляет параметр типа, есть много других дополнительных вопросов, на которые можно ответить при помощи отражения. Можно определить источник этого параметра типа, его положения и его ограничения.

Параметр типа или аргумент типа

Чтобы определить, является ли конкретный элемент массива параметром типа или аргументом типа, следует использовать свойство IsGenericParameter. Если элемент является параметром типа, свойство IsGenericParameter имеет значение true.

Универсальный тип может быть открытым, не являясь определением универсального типа. В таком случае он представляет собой набор аргументов типа и параметров типа. Так, в следующем параметре класс D является производным от типа, созданного путем замены первым параметром типа класса D вторым параметром типа класса B.

class B<T, U> {}
class D<V, W> : B<int, V> {}
Class B(Of T, U)
End Class
Class D(Of V, W)
    Inherits B(Of Integer, V)
End Class
generic<typename T, typename U> ref class B {};
generic<typename V, typename W> ref class D : B<int, V> {};

В результате получения объекта Type, представляющего класс D<V, W>, и использования свойства BaseType для получения его базового типа, итоговый тип type B<int, V> является открытым, однако при этом не представляет собой определение универсального типа.

Источник универсального параметра

Параметр универсального типа может быть получен из изучаемого типа, инкапсулирующего типа или из универсального метода. Источник параметра универсального типа можно определить следующим образом:

  • Во-первых, можно воспользоваться свойством DeclaringMethod, чтобы определить, получен ли параметр типа из универсального метода. Если значение свойства не является пустой ссылкой (Nothing в Visual Basic), источник является универсальным методом.

  • Если источник не является универсальным методом, для определения универсального типа, которому принадлежит параметр универсального типа, следует использовать свойство DeclaringType.

Если параметр типа относится к универсальному методу, свойство DeclaringType возвращает тип, объявивший универсальный метод, который является несоответствующим.

Положение универсального параметра

Иногда необходимо определить положение параметра типа в списке параметров типа объявившего класса. Например, предположим, что есть объект Type, представляющий тип B<int, V> из предыдущего примера. Метод GetGenericArguments предоставляет список аргументов типа, а при изучении класса V можно воспользоваться свойствами DeclaringMethod и DeclaringType, чтобы выявить источник этого класса. Затем при помощи свойства GenericParameterPosition можно определить его положение в списке параметров типа, где он был определен. В этом примере класс V находится в положении 0 (ноль) в списке параметров типа, где он был определен.

Ограничения для базового типа и интерфейса

Метод GetGenericParameterConstraints следует использовать для получения ограничения базового типа и ограничений интерфейса для параметра типа. Порядок элементов массива не имеет значения. Элемент представляет ограничение интерфейса, если оно является типом интерфейса.

Особые ограничения

Свойство GenericParameterAttributes получает значение GenericParameterAttributes, которое определяет особые ограничения. Параметр типа может быть ограничен как ссылочный тип либо тип необнуляемого значения, а также может быть ограничен конструктором по умолчанию.

Инварианты

Таблицу неизменяемых условий для общих терминов в отражении для универсальных типов см. в Type.IsGenericType. Дополнительные термины, относящиеся к универсальным методам, см. в MethodInfo.IsGenericMethod.

См. также

Задачи

Практическое руководство. Изучение универсальных типов и создание их экземпляров при помощи отражения

Основные понятия

Общие сведения об универсальных шаблонах в .NET Framework

Просмотр сведений о типах

Ссылки

Type

MethodInfo

Type.IsGenericType

MethodInfo.IsGenericMethod