Come posso vedere se GenericTypeDefinition implementa IEnumerable

Ho un metodo che controlla se un tipo è generico e quindi controlla se GenericTypeDefinition è di IEnumerable .

 static Type GetEnumerableType(Type type) { if(type.IsGenericType) { var genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(IEnumerable)) { return type.GetGenericArguments()[0]; } } return null; } 

Funziona come un fascino se è un object IEnumerable. Se il GenericTypeDefinition è IList o List non funziona. Ho provato..

 typeof(IEnumerable).IsAssignableFrom(genericTypeDefinition) 

..senza successo. Certamente ci deve essere un modo migliore per incatenare le altre dichiarazioni?

È ansible utilizzare GetInterfaces per verificare se un tipo implementa IEnumerable<> così

 Type type = new List().GetType(); if (type.IsGenericType) { var genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition.GetInterfaces() .Any( t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>))) { return type.GetGenericArguments()[0]; } } 

Ho finito per immergermi più in profondità nella gestione generale degli oggetti e ho trovato questo modo più complesso di ogni ipotesi originale. Questo è il metodo che sto usando ora:

 /// Check whether the specified type is enumerable. /// The type. /// IEnumerable{int} would be int ///  /// [OPTIONAL] if set to true [exclude string]. Strings are enumerable as char[] /// this is likely not something you want. Default is true (string will return false) ///  /// true supplied type is enumerable otherwise false public static bool IsEnumerable(this Type type, out Type underlyingType, bool excludeString = true) { underlyingType = null; if (type.IsEnum || type.IsPrimitive || type.IsValueType) return false; if (excludeString && type == typeof(string)) return false; if (type.IsGenericType) { if (type.IsTypeDefinitionEnumerable() || type.GetInterfaces() .Any(t => t.IsSelfEnumerable() || t.IsTypeDefinitionEnumerable())) { underlyingType = type.GetGenericArguments()[0]; return true; } } //direct implementations of IEnumerable, inheritance from List etc var enumerableOrNull = type.GetInterfaces() .FirstOrDefault(t => t.IsTypeDefinitionEnumerable()); if (enumerableOrNull == null) return false; underlyingType = enumerableOrNull.GetGenericArguments()[0]; return true; } 

//

 private static bool IsSelfEnumerable(this Type type) { bool isDirectly = type == typeof(IEnumerable<>); return isDirectly; } private static bool IsTypeDefinitionEnumerable(this Type type) { bool isViaInterfaces = type.IsGenericType && type.GetGenericTypeDefinition().IsSelfEnumerable(); return isViaInterfaces; } 

Questa soluzione è testata:

Install-Package NUnit -Version 2.6.4

Installa-pacchetto dovrei

 [Test] public void List_is_enumerable() { var sut = new List(); Type underlyingType; var result = sut.IsEnumerable(out underlyingType); result.ShouldBeTrue(); underlyingType.ShouldBe(typeof(int)); } 

//

 [Test] public void Yield_return_is_enumerable() { var sut = Yielded(); Type underlyingType; var result = sut.IsEnumerable(out underlyingType); result.ShouldBeTrue(); underlyingType.ShouldBe(typeof(int)); } private IEnumerable Yielded() { for (int i = 0; i < 3; i++) { yield return i; } } 

//

 [Test] public void int_is_not_an_enumerable() { var sut = 5; Type underlyingType; var result = sut.IsEnumerable(out underlyingType); result.ShouldBe(false); underlyingType.ShouldBeNull(); } [Test] public void object_is_not_an_enumerable() { var sut = new { foo = 1}; Type underlyingType; var result = sut.IsEnumerable(out underlyingType); result.ShouldBe(false); underlyingType.ShouldBeNull(); } 

Tenuto per i posteri. Questo non risponde alla domanda originale ma era chiaramente utile per i membri qui.

 public static bool IsA(this Type type) { return typeof (T).IsAssignableFrom(type); }