从IEnumerable <T>获得typesT.
有没有办法通过reflection从IEnumerable<T>
检索typesT
?
例如
我有一个variablesIEnumerable<Child>
信息; 我想通过reflection来检索孩子的types
IEnumerable<T> myEnumerable; Type type = myEnumerable.GetType().GetGenericArguments()[0];
正是如此,
IEnumerable<string> strings = new List<string>(); Console.WriteLine(strings.GetType().GetGenericArguments()[0]);
打印System.String
。
请参阅MSDN的Type.GetGenericArguments
。
编辑:我相信这将解决在评论中的关注:
// returns an enumeration of T where o : IEnumerable<T> public IEnumerable<Type> GetGenericIEnumerables(object o) { return o.GetType() .GetInterfaces() .Where(t => t.IsGenericType == true && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)) .Select(t => t.GetGenericArguments()[0]); }
一些对象实现多个genericsIEnumerable
因此有必要返回它们的枚举。
编辑:虽然,我不得不说,一个类实现多个IEnumerable<T>
是一个可怕的想法。
我只是做一个扩展方法。 这一切与我扔在它的一切。
public static Type GetItemType<T>(this IEnumerable<T> enumerable) { return typeof(T); }
如果你知道IEnumerable<T>
(通过generics),那么typeof(T)
应该工作。 否则(对于object
,或非genericsIEnumerable
),请检查实现的接口:
object obj = new string[] { "abc", "def" }; Type type = null; foreach (Type iType in obj.GetType().GetInterfaces()) { if (iType.IsGenericType && iType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) { type = iType.GetGenericArguments()[0]; break; } } if (type != null) Console.WriteLine(type);
我有一个类似的问题。 所选答案适用于实际情况。 在我的情况下,我只有一个types(来自PropertyInfo
)。
当types本身是typeof(IEnumerable<T>)
而不是typeof(IEnumerable<T>)
的实现时,所选答案失败。
对于这种情况下面的工作:
public static Type GetAnyElementType(Type type) { // Type is Array // short-circuit if you expect lots of arrays if (type.IsArray) return type.GetElementType(); // type is IEnumerable<T>; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (IEnumerable<>)) return type.GetGenericArguments()[0]; // type implements/extends IEnumerable<T>; var enumType = type.GetInterfaces() .Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)) .Select(t => t.GenericTypeArguments[0]).FirstOrDefault(); return enumType ?? type; }
考虑对选定的答案进行投票,如果你觉得这个代码有用的话。
非常感谢您的讨论。 我用它作为下面的解决scheme的基础,这适用于我感兴趣的所有情况(IEnumerable,派生类等)。 以为我应该在这里分享以防万一任何人需要它也:
Type GetItemType(object someCollection) { var type = someCollection.GetType(); var ienum = type.GetInterface(typeof(IEnumerable<>).Name); return ienum != null ? ienum.GetGenericArguments()[0] : null; }
只要使用typeof(T)
编辑:或使用.GetType()。GetGenericParameter()对实例化的对象,如果你没有T.
对于更简单的情况来说,它可能是一个IEnumerable<T>
或T
-note使用GenericTypeArguments
而不是GetGenericArguments()
。
Type inputType = o.GetType(); Type genericType; if ((inputType.Name.StartsWith("IEnumerable")) && ((genericType = inputType.GenericTypeArguments.FirstOrDefault()) != null)) { return genericType; } else { return inputType; }
typeof(IEnumerable<Foo>)
。 GetGenericArguments()
[0]
将返回第一个generics参数 – 在这种情况下, typeof(Foo)
。
这是对Eli Algranti的解决scheme的改进,因为它也可以在inheritance树中IEnumerable<>
types的任何级别上工作。
此解决scheme将从任何Type
获取元素Type
。 如果该types不是IEnumerable<>
,则它将返回传入的types。对于对象,请使用GetType
。 对于types,使用typeof
,然后在结果上调用这个扩展方法。
public static Type GetGenericElementType(this Type type) { // Short-circuit for Array types if (typeof(Array).IsAssignableFrom(type)) { return type.GetElementType(); } while (true) { // Type is IEnumerable<T> if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) { return type.GetGenericArguments().First(); } // Type implements/extends IEnumerable<T> Type elementType = (from subType in type.GetInterfaces() let retType = subType.GetGenericElementType() where retType != subType select retType).FirstOrDefault(); if (elementType != null) { return elementType; } if (type.BaseType == null) { return type; } type = type.BaseType; } }