将IEnumerable转换/转换为IEnumerable <T>

我有一个类(一个Web控件)具有IEnumerabletypes的属性,并希望使用LINQ的参数。

有没有办法通过reflection投入/转换/调用IEnumerable <T>不知道编译时的types?

Method void (IEnumerable source) { var enumerator = source.GetEnumerator(); if (enumerator.MoveNext()) { var type = enumerator.Current.GetType(); Method2<type>(source); // this doesn't work! I know! } } void Method2<T>(IEnumerable<T> source) {} 

你的Method2真的关心它的types吗? 如果没有,你可以调用Cast<object>()

 void Method (IEnumerable source) { Method2(source.Cast<object>()); } 

如果你确实需要得到正确的types,你需要使用reflection。

就像是:

 MethodInfo method = typeof(MyType).GetMethod("Method2"); MethodInfo generic = method.MakeGenericMethod(type); generic.Invoke(this, new object[] {source}); 

这并不理想,特别是,如果源不完全是一个IEnumerable<type>那么调用将失败。 例如,如果第一个元素碰巧是一个string,但是源代码是一个List<object> ,则会遇到问题。

您可能想要重构您的代码以使用IEnumerable.Cast<T>

像这样使用它:

 IEnumerable mySet = GetData(); var query = from x in mySet.Cast<int>() where x > 2 select x; 

使用.NET 4,您只需将source传递给方法即可。 这将导致正确的generics重载在运行时被parsing,没有任何难看的reflection代码:

 void Method(IEnumerable source) { var enumerator = source.GetEnumerator(); if (enumerator.MoveNext()) { Method2((dynamic)source); } } 

和Jon的第二个解决scheme一样,只有当你的源代码实际上是一个IEnumerable<T>才会有效。 如果它是一个纯IEnumerable那么您将需要创build另一个方法,将其转换为正确的IEnumerable<T>types,如下面的解决scheme:

 IEnumerable<T> Convert<T>(IEnumerable source, T firstItem) { // Note: firstItem parameter is unused and is just for resolving type of T foreach(var item in source) { yield return (T)item; } } void Method(IEnumerable source) { var enumerator = source.GetEnumerator(); if (enumerator.MoveNext()) { dynamic firstItem = enumerator.Current; dynamic typedEnumerable = Convert(source, firstItem); Method2(typedEnumerable); } } 

这是几年后,但我解决了List<Object>问题。

 void Method(IEnumerable source) { var enumerator = source.GetEnumerator(); if (enumerator.MoveNext()) { MethodInfo method = typeof(MyClass).GetMethod("Method2"); MethodInfo generic; Type type = enumerator.Current.GetType(); bool sameType = true; while (enumerator.MoveNext()) { if (enumerator.Current.GetType() != type) { sameType = false; break; } } if (sameType) generic = method.MakeGenericMethod(type); else generic = method.MakeGenericMethod(typeof(object)); generic.Invoke(this, new object[] { source }); } }