2009-10-30 12 views
11

Próbuję wykryć czy dana instancja typu obiektu jest rodzajowy „IEnumerable” ...NET Reflection: Wykrywanie IEnumerable <T>

Najlepszym mogę wymyślić to:

// theType might be typeof(IEnumerable<string>) for example... or it might not 
bool isGenericEnumerable = theType.GetGenericTypeDefinition() == typeof(IEnumerable<object>).GetGenericTypeDefinition() 
if(isGenericEnumerable) 
{ 
    Type enumType = theType.GetGenericArguments()[0]; 
    etc. ...// enumType is now typeof(string) 

Ale wydaje się to nieco pośrednie - czy istnieje bardziej bezpośredni/elegancki sposób na zrobienie tego?

+0

Proszę zobaczyć moje obserwacje: http://stackoverflow.com/questions/1650310/net-reflection-determinating-whether-an-array-of-t-would-be-convertible-to-some-o –

Odpowiedz

22

Można użyć

if(theType.IsGenericType && theType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) 
{ 
    Type underlyingType = theType.GetGenericArguments()[0]; 
    //do something here 
} 

EDIT: dodano sprawdzanie IsGenericType, dzięki za użytecznych uwag

+2

To bardzo zły tyłek, właśnie tam. –

+2

jeśli theType nie jest generyczny, rzuci "InvalidOperationException" - niezbyt dobre rozwiązanie dla sprawdzania IMHO. – Lucero

+3

Działa to tylko wtedy, gdy "typ" jest dokładnie typu (IEnumerable <>), a nie, jeśli typ implementuje interfejs. Mam nadzieję, że właśnie o to prosisz. –

2

Należy pamiętać, że nie można nazwać GetGenericTypeDefinition() od typu non-generic zatem najpierw sprawdzić z IsGenericType.

Nie jestem pewien, czy chcesz sprawdzić, czy typ implementuje ogólny IEnumerable<>, czy też chcesz sprawdzić, czy typ interfejsu to IEnumerable<>. W pierwszym przypadku należy stosować następujące kod (wewnętrzna kontrola z interfaceType to drugi przypadek):

if (typeof(IEnumerable).IsAssignableFrom(type)) { 
    foreach (Type interfaceType in type.GetInterfaces()) { 
     if (interfaceType.IsGenericType && (interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))) { 
      Console.WriteLine("{0} implements {1} enumerator", type.FullName, interfaceType.FullName); // is a match 
     } 
    } 
} 
+0

jest kodem odnoszącym się do starszego (nie generycznego) interfejsu IEnumerable? –

+0

Wyjaśnię moje pytanie ... –

+0

Tak, ponieważ generyczny oznacza nietypowy, jest to szybka kontrola, aby upewnić się, że warto w ogóle przejść przez interfejsy. Jeśli 'IEnumerable' (non-generic) nie jest zaimplementowane,' IEnumerable <> '(generic) też nie może być. – Lucero

4

można użyć ten kawałek kodu w celu określenia, czy dany typ implementuje interfejs IEnumerable<T>.

Type type = typeof(ICollection<string>); 

bool isEnumerable = type.GetInterfaces()  // Get all interfaces. 
    .Where(i => i.IsGenericType)    // Filter to only generic. 
    .Select(i => i.GetGenericTypeDefinition()) // Get their generic def. 
    .Where(i => i == typeof(IEnumerable<>)) // Get those which match. 
    .Count() > 0; 

Będzie działać na każdym interfejsie, jednak nie będzie praca jeśli typ przechodzą w jest IEnumerable<T>.

Powinieneś być w stanie zmodyfikować, aby sprawdzić argumenty typu przekazywane do każdego interfejsu.

+0

Zamiast Where(). Count() możesz użyć Any(). – Fred

Powiązane problemy