Verificar se um tipo é uma concretização de um genérico em .NET

 
Há uns dias estava a trabalhar com um colega meu e algures no meio de uns genéricos surgiu-nos a necessidade de saber se um dado objecto é instância de um tipo que é concretização de um dado genérico. Fomos um pouco preguiçosos e, em vez de procurar na documentação, perguntámos ao Eng.º Miguel Carvalho como resolver o problema. E a solução é muito simples! O que se pretende é algo deste género:
static void Main(string[] args)
{
    int i = 0;
    List<int> list = new List<int>();
    Dictionary<int,string> dict = new Dictionary<int,string>();

    Console.WriteLine(IsSpecificationOfGenericType(i, typeof(List<>)));             // False
    Console.WriteLine(IsSpecificationOfGenericType(list, typeof(List<>)));          // True
    Console.WriteLine(IsSpecificationOfGenericType(dict, typeof(List<>)));          // False
    Console.WriteLine(IsSpecificationOfGenericType(dict, typeof(Dictionary<,>)));   // True
}
A primeira coisa a reparar é como indicar os tipos "base" dos genéricos: utiliza-se a sintaxe <,>; por exemplo, para List<T> utiliza-se typeof(List<>). Antes de passar à implementação do método auxiliar IsSpecificationOfGenericType vejamos três membros do tipo "Type":
 
– IsGenericType: Gets a value indicating whether the current type is a generic type.
– GetGenericTypeDefinition: Returns a Type object that represents a generic type definition from which the current generic type can be constructed.
– IsGenericTypeDefinition: Indicates whether the current Type represents a generic type definition, from which other generic types can be constructed.
Com estas propriedades e sabendo que a instância de Type que representa um tipo é única, a implementação do método auxiliar fica muito simples:
static bool IsSpecificationOfGenericType(object o, Type genericType)
{
    if (!genericType.IsGenericTypeDefinition) 
        throw new InvalidOperationException("The 'genericType' parameter must be a generic type definition");
    Type t = o.GetType();
    return t.IsGenericType && t.GetGenericTypeDefinition() == genericType;
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s