我有一个类(一个Web控件),它具有IEnumerable类型的属性,并希望使用LINQ处理该参数.
有没有办法通过反射转换/转换/调用IEnumerable <T>在编译时不知道类型?
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) {}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 64
你Method2真的关心它的类型吗?如果没有,你可以打电话Cast<object>():
void Method (IEnumerable source)
{
Method2(source.Cast<object>());
}
Run Code Online (Sandbox Code Playgroud)
如果你肯定需要获得正确的类型,你需要使用反射.
就像是:
MethodInfo method = typeof(MyType).GetMethod("Method2");
MethodInfo generic = method.MakeGenericMethod(type);
generic.Invoke(this, new object[] {source});
Run Code Online (Sandbox Code Playgroud)
虽然它并不理想......特别是,如果source不完全是,IEnumerable<type>那么调用将失败.例如,如果第一个元素恰好是一个字符串,但是source是a List<object>,那么你就会遇到问题.
Bri*_*sio 11
您可能希望重构代码以供使用 IEnumerable.Cast<T>
像这样使用它:
IEnumerable mySet = GetData();
var query = from x in mySet.Cast<int>()
where x > 2
select x;
Run Code Online (Sandbox Code Playgroud)
使用.NET 4,您可以在将其传递给方法之前进行强制source转换dynamic。这将导致在运行时解析正确的泛型重载,而无需任何丑陋的反射代码:
void Method(IEnumerable source)
{
var enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
{
Method2((dynamic)source);
}
}
Run Code Online (Sandbox Code Playgroud)
与 Jon 的第二个解决方案一样,只有当您的源实际上是IEnumerable<T>. 如果它是普通类型IEnumerable,那么您需要创建另一个方法将其转换为正确的IEnumerable<T>类型,如以下解决方案所示:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28277 次 |
| 最近记录: |