Reflexão e tipos genéricos

 

Do ponto de vista da reflexão, a diferença entre um tipo genérico e um tipo comum é que um tipo genérico associado a ela um conjunto de parâmetros de tipo (se for uma definição de tipo genérico) ou argumentos de tipo (se for um tipo construído). Um método genérico é diferente de um método comum da mesma maneira.

Há duas chaves para entender como reflexão trata tipos e métodos genéricos:

  • Parâmetros de tipo de definições de tipo genérico e método genérico são representados por instâncias de Type classe.

    System_CAPS_noteObservação

    Muitas propriedades e métodos de Type têm um comportamento diferente quando um Type objeto representa um parâmetro de tipo genérico. Essas diferenças são documentadas nos tópicos de propriedade e método. Por exemplo, consulte IsAutoClass e DeclaringType. Além disso, alguns membros são válido somente quando uma Type objeto representa um parâmetro de tipo genérico. Por exemplo, consulte GetGenericTypeDefinition.

  • Se uma instância do Type representa um tipo genérico, em seguida, ele inclui uma matriz de tipos que representam os parâmetros de tipo (para definições de tipo genérico) ou os argumentos de tipo (para tipos construídos). O mesmo é verdadeiro de uma instância de MethodInfo classe que representa um método genérico.

Reflexão fornece métodos Type e MethodInfo que permitem a você acessar a matriz de parâmetros de tipo para determinar se uma instância de Type representa um parâmetro de tipo ou um tipo real.

Por exemplo de código demonstra os métodos discutidos aqui, consulte Como examinar tipos genéricos e criar instâncias deles com a reflexão.

A discussão a seguir pressupõe familiaridade com a terminologia de genéricos, como a diferença entre os parâmetros de tipo e argumentos e tipos construídos abertos ou fechados. Para obter mais informações, consulte Genéricos no .NET Framework.

Esta visão geral consiste das seguintes seções:

Quando você usa a reflexão para examinar um tipo desconhecido, representado por uma instância de Type, use o IsGenericType para determinar se o tipo desconhecido é genérico. Retorna true se o tipo for genérico. Da mesma forma, quando você examinar um método desconhecido, representado por uma instância de MethodInfo classe, use o IsGenericMethod propriedade para determinar se o método é genérico.

Use o IsGenericTypeDefinition para determinar se um Type objeto representa uma definição de tipo genérico e use o IsGenericMethodDefinition método para determinar se um MethodInfo representa uma definição de método genérico.

Definições de tipo e um método genéricas são os modelos que podem ser instanciados tipos serão criados. Tipos genéricos na biblioteca de classes do .NET Framework, como Dictionary<TKey, TValue>, definições de tipo genérico.

Um tipo genérico ou método é fechado se tipos podem ser instanciados foram substituídos para todos os seus parâmetros de tipo, incluindo todos os parâmetros de tipo de todos os tipos de delimitadores. Você só pode criar uma instância de um tipo genérico se ele é fechado. O Type.ContainsGenericParameters propriedade retorna true se um tipo é aberto. Para métodos, o MethodInfo.ContainsGenericParameters método executa a mesma função.

Voltar ao início

Quando você tiver um tipo genérico ou a definição do método, use o MakeGenericType método para criar um tipo genérico fechado ou MakeGenericMethod método para criar um MethodInfo para um método genérico fechado.

Se você tiver um tipo genérico aberto ou método não é um tipo genérico ou a definição do método, você não pode criar instâncias dele e não pode fornecer os parâmetros de tipo que estão faltando. Você deve ter uma definição de tipo ou método genérica. Use o GetGenericTypeDefinition método para obter a definição de tipo genérico ou o GetGenericMethodDefinition método para obter a definição de método genérico.

Por exemplo, se você tiver um Type objeto representando Dictionary<int, string> (Dictionary(Of Integer, String) no Visual Basic) e você deseja criar o tipo Dictionary<string, MyClass>, você pode usar o GetGenericTypeDefinition método para obter um Type representando Dictionary<TKey, TValue> e, em seguida, usar o MakeGenericType método para produzir um Type representando Dictionary<int, MyClass>.

Para obter um exemplo de um tipo genérico aberto que não é um tipo genérico, consulte "Tipo de parâmetro ou tipo de argumento" posteriormente neste tópico.

Voltar ao início

Use o Type.GetGenericArguments método para obter uma matriz de Type objetos que representam os parâmetros de tipo ou os argumentos de tipo de um tipo genérico e usarem o MethodInfo.GetGenericArguments método para fazer o mesmo para um método genérico.

Se você souber que uma Type objeto representa um parâmetro de tipo, há muitas perguntas adicionais de reflexão pode responder. Você pode determinar a origem do parâmetro de tipo, sua posição e suas restrições.

Para determinar se um determinado elemento da matriz é um parâmetro de tipo ou um argumento de tipo, use o IsGenericParameter propriedade. O IsGenericParameter é de propriedade true se o elemento é um parâmetro de tipo.

Um tipo genérico pode ser aberto sem ser uma definição de tipo genérico, caso em que ele tem uma combinação de parâmetros de tipo e argumentos de tipo. Por exemplo, no código a seguir, classe D deriva de um tipo criado, substituindo o primeiro parâmetro de tipo de D para o segundo parâmetro de tipo de B.

class B<T, U> {}
class D<V, W> : B<int, V> {}

Se você obtiver uma Type objeto representando D<V, W> e usar o BaseType propriedade para obter o tipo base, resultante type B<int, V> é aberto, mas não é uma definição de tipo genérico.

Um parâmetro de tipo genérico pode ser do tipo que você está examinando, de um tipo de delimitador ou de um método genérico. Você pode determinar a origem do parâmetro de tipo genérico da seguinte maneira:

  • Primeiro, use o DeclaringMethod para determinar se o parâmetro de tipo é proveniente de um método genérico. Se o valor da propriedade não é uma referência nula (Nothing no Visual Basic), em seguida, a origem é um método genérico.

  • Se a fonte não é um método genérico, use o DeclaringType pertence para determinar o tipo genérico do parâmetro de tipo genérico.

Se o parâmetro de tipo pertencer a um método genérico, o DeclaringType propriedade retorna o tipo declarado o método genérico, que é irrelevante.

Em raras situações, é necessário determinar a posição de um parâmetro de tipo na lista de parâmetros de tipo de sua classe declarante. Por exemplo, suponha que você tenha uma Type objeto representando o B<int, V> tipo do exemplo anterior. O GetGenericArguments método fornece uma lista de argumentos de tipo, e ao examinar V você pode usar o DeclaringMethod e DeclaringType Propriedades para descobrir onde ele vem. Você pode usar o GenericParameterPosition para determinar sua posição na lista de parâmetros de tipo em que ela foi definida. Neste exemplo, V está na posição 0 (zero) na lista de parâmetros de tipo em que ela foi definida.

Use o GetGenericParameterConstraints método para obter o tipo base restrições de restrição e a interface de um parâmetro de tipo. A ordem dos elementos da matriz não é significativa. Um elemento representa uma restrição de interface se ele for um tipo de interface.

O GenericParameterAttributes propriedade obtém um GenericParameterAttributes valor que indica a variância (covariância ou contravariância) e as restrições especiais de um parâmetro de tipo.

Para determinar se um parâmetro de tipo é covariant ou contravariant, aplicar o GenericParameterAttributes.VarianceMask máscara para o GenericParameterAttributes valor que é retornado pelo GenericParameterAttributes propriedade. Se o resultado for GenericParameterAttributes.None, o parâmetro de tipo é invariável. Consulte Covariância e contravariância em genéricos.

Para determinar as restrições especiais de um parâmetro de tipo, aplicar o GenericParameterAttributes.SpecialConstraintMask máscara para o GenericParameterAttributes valor que é retornado pelo GenericParameterAttributes propriedade. Se o resultado for GenericParameterAttributes.None, não há nenhuma restrição especial. Um parâmetro de tipo pode ser restringido a ser um tipo de referência, para ser um tipo de valor não nulo e tem um construtor padrão.

Voltar ao início

Para uma tabela de condições invariáveis para termos comuns de reflexão de tipos genéricos, consulte Type.IsGenericType. Por termos adicionais relacionadas a métodos genéricos, consulte MethodInfo.IsGenericMethod.

Voltar ao início

Título

Descrição

Como examinar tipos genéricos e criar instâncias deles com a reflexão

Mostra como usar as propriedades e métodos de Type e MethodInfo para examinar tipos genéricos.

Genéricos no .NET Framework

Descreve o recurso genéricos e como ele tem suporte no .NET Framework.

Como definir um tipo genérico com a emissão de reflexão

Mostra como usar a reflexão emitir para gerar tipos genéricos em assemblies dinâmicos.

Exibindo informações de tipo

Descreve o Type de classe e fornece exemplos de código que ilustram como usar Type com várias classes de reflexão para obter informações sobre construtores, métodos, campos, propriedades e eventos.

Mostrar: