2009-10-30 9 views
11

J'essaie de détecter si une instance particulière d'un objet type est un « IEnumerable » générique ...Réflexion .NET: Détection IEnumerable <T>

Le meilleur que je peux trouver est:

// 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) 

Mais cela semble un peu indirect - existe-t-il un moyen plus direct/élégant de le faire?

+0

s'il vous plaît voir mon suivi: http://stackoverflow.com/questions/1650310/net-reflection-determining-whether-an-array-of-t-would-be-convertible-to-some-o –

Répondre

22

Vous pouvez utiliser

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

EDIT: ajout de la vérification des IsGenericType, merci pour les commentaires utiles

+2

C'est très mauvais cul, juste là. –

+2

si theType n'est pas générique, il lancera un 'InvalidOperationException' - pas une très bonne solution pour un contrôle à mon humble avis. – Lucero

+3

Cela ne fonctionne que si 'theType' est exactement typeof (IEnumerable <>), pas si le type implémente l'interface. J'espère que c'est ce que vous recherchez. –

2

Notez que vous ne pouvez pas appeler GetGenericTypeDefinition() sur un type non générique, donc, tout d'abord vérifier avec IsGenericType.

Je ne suis pas sûr si vous voulez vérifier si un type implémente un générique IEnumerable<> ou si vous voulez voir si un type d'interface est IEnumerable<>. Pour le premier cas, utilisez le code suivant (la vérification interne avec interfaceType est le second cas):

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

est ce code se référant à l'interface IEnumerable héritée (non générique)? –

+0

Je vais clarifier ma question ... –

+0

Oui, parce que le générique implique le non-générique, c'est une vérification rapide pour s'assurer qu'il vaut la peine de passer par-dessus les interfaces du tout. Si 'IEnumerable' (non générique) n'est pas implémenté,' IEnumerable <> '(generic) ne peut pas l'être non plus. – Lucero

4

Vous pouvez utiliser ce morceau de code pour déterminer si un type particulier implémente l'interface 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; 

Il fonctionnera pour toute interface, mais il ne sera pas travail si le type que vous passer est IEnumerable<T>.

Vous devriez pouvoir le modifier pour vérifier les arguments de type transmis à chaque interface.

+0

Au lieu de Where(). Count(), vous pouvez utiliser Any(). – Fred

Questions connexes