2011-09-02 11 views
8

Tengo una matriz de PropertyInfo que representa las propiedades de una clase. Algunas de estas propiedades son de tipo ICollection<T>, pero T varía a través de las propiedades - Tengo algunos ICollection<string>, algunos ICollection<int>, etc.¿Cómo puedo encontrar el tipo de T en una colección C# genérica de T cuando todo lo que sé es el tipo de la colección?

I pueden identificar fácilmente cuál de las propiedades son de tipo ICollection<> utilizando el método GetGenericTypeDefinition() en tipo, pero me resulta imposible obtener el tipo de T - la int o cadena en mi ejemplo anterior.

¿Hay alguna manera de hacerlo?

IDocument item 
PropertyInfo[] documentProperties = item.GetType().GetProperties();  
PropertyInfo property = documentProperties.First(); 
Type typeOfProperty = property.PropertyType; 

if (typeOfProperty.IsGenericType) 
{ 
    Type typeOfProperty = property.PropertyType.GetGenericTypeDefinition(); 

    if (typeOfProperty == typeof(ICollection<>) 
    { 
     // find out the type of T of the ICollection<T> 
     // and act accordingly 
    } 
} 

Respuesta

8

Si sabe que va a ser ICollection<X>, pero no saben X, eso es bastante fácil con GetGenericArguments:

if (typeOfProperty.IsGenericype) 
{ 
    Type genericDefinition = typeOfProperty.GetGenericTypeDefinition(); 

    if (genericDefinition == typeof(ICollection<>) 
    { 
     // Note that we're calling GetGenericArguments on typeOfProperty, 
     // not genericDefinition. 
     Type typeArgument = typeOfProperty.GetGenericArguments()[0]; 
     // typeArgument is now the type you want... 
    } 
} 

Se hace más difícil cuando el tipo es algún tipo, que implementa ICollection<T> pero puede ser genérico Suena como si estuviera en una posición mejor :)

+0

Maldita sea! Me venciste por 20 segundos. Cruzamos :-) – Steven

+1

@Steven: ¡Acabas de conseguir a Jon Skeeted! –

+0

Estaba llamando a GetGenericArguments en genericDefinition, no en typeOfProperty. He corregido mi descuido y ahora todo está bien. El comentario que eliminé hizo que tu comentario no tenga sentido, disculpas. – Jason

4

Creo que esto es lo que busca:

typeOfProperty.GetGenericArguments()[0]; 

que va a devolver la pieza T de una lista genérica <T> por ejemplo. solución

1

de Jon rendirá T. Dependiendo del contexto, puede que tenga que acceder al tipo de retorno captador lugar con el fin de conseguir int, string, etc. Por ejemplo ...

// The following example will output "T" 
typeOfProperty = property.PropertyType.GetGenericTypeDefinition(); 
Type genericDefinition = typeOfProperty.GetGenericTypeDefinition(); 
if (genericDefinition == typeof(ICollection<>)) 
{ 
    Type t1 = typeOfProperty.GetGenericArguments()[0]; 
    Console.WriteLine(t1.ToString()); 
} 

// Instead you might need to do something like the following... 
// This example will output the declared type (e.g., "Int32", "String", etc...) 
typeOfProperty = property.GetGetMethod().ReturnType; 
if (typeOfProperty.IsGenericType) 
{ 
    Type t2 = typeOfProperty.GetGenericArguments()[0]; 
    Console.WriteLine(t2.ToString()); 
} 
Cuestiones relacionadas