如何查看GenericTypeDefinition是否实现IEnumerable

我有一个方法来检查类型是否是通用的,然后检查GenericTypeDefinition是否是IEnumerable

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

如果它是一个IEnumerable,它就像一个魅力。 如果GenericTypeDefinition是IListList则它不起作用。 我试过了..

 typeof(IEnumerable).IsAssignableFrom(genericTypeDefinition) 

..没有成功。 当然必须有更好的方法然后链接其他语句?

您可以使用GetInterfaces来检查类型是否实现IEnumerable<>

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

我结束了对一般物体处理的深入研究,发现这种方式比任何原始假设更复杂。 这是我现在使用的方法:

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

该解决方案经过测试:

安装包NUnit -Version 2.6.4

应该安装包

 [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(); } 

为后代举行。 这不符合原始问题,但对于这里的成员显然是有用的。

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