2011-09-02 16 views
8

Ho una matrice di PropertyInfo che rappresenta le proprietà in una classe. Alcune di queste proprietà sono di tipo ICollection<T>, ma T varia tra le proprietà - ho qualche ICollection<string>, alcuni ICollection<int>, eccCome posso trovare il tipo di T in una collezione generica di C# di T quando tutto quello che so è il tipo di collezione?

posso facilmente identificare quale delle proprietà sono di tipo ICollection<> utilizzando il metodo GetGenericTypeDefinition() su tipo, ma trovo impossibile ottenere il tipo di T - int o stringa nel mio esempio sopra.

C'è un modo per farlo?

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 
    } 
} 

risposta

8

Se si sa che sarà ICollection<X> ma non so X, che è abbastanza facile 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... 
    } 
} 

Diventa sempre più difficile quando il tipo è un certo tipo che implementa ICollection<T> ma può essere di per sé generico. Sembra che tu sei in una posizione migliore :)

+0

Dannazione! Mi hai battuto per 20 secondi. Attraversiamo postato :-) – Steven

+1

@Steven: hai appena ottenuto Jon Skeeted! –

+0

Stavo chiamando GetGenericArguments su genericDefinition, non su typeOfProperty. Ho corretto la mia supervisione e ora tutto va bene. Il commento che ho cancellato ha reso il tuo commento privo di senso, scuse. – Jason

4

Credo che questo è quello che stai cercando:

typeOfProperty.GetGenericArguments()[0]; 

che restituirà la parte T di un elenco generico <T> per esempio. soluzione

1

di Jon produrrà T. A seconda del contesto, potrebbe essere necessario accedere al tipo di ritorno getter invece al fine di ottenere int, string, ecc, ad esempio ...

// 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()); 
} 
Problemi correlati