给定班级:
public class A<T>
{
public void Handle(object payload)
{
if(IsEnumerable(payload)) //assume this works
{
var closedMethod = GetType()
.GetMethod(
"HandleIEnumerable",
BindingFlags.NonPublic | BindingFlags.Instance)
.MakeGenericMethod(
GetFirstGenericArgument(typeof(T)));
closedMethod
.Invoke(
this,
null); //Exception thrown by the Invoke operation
//Debugging shows type as HandleIEnumerable[T]
return;
}
//handle other things
}
//This was added because in the above, I can't interact with "T"
// as IEnumerable<U> without using reflection
// to jump through the hoops
private void HandleIEnumerable<U>(object payload)
{
foreach (var element in payload as IEnumerable<U>)
{
// do something to element
}
}
private bool IsEnumerable(object payload)
{
var theType = typeof(T);
return
theType.IsGenericType
&& (theType.GetGenericTypeDefinition() == typeof(IEnumerable<>));
}
private Type GetFirstGenericArgument(Type t)
{
return t.GetGenericTypeDefinition().GetGenericArguments()[0];
}
}
测试用例暴露了一个异常:
[TestMethod]
public void A_Handle_IEnumerable()
{
new ClassLibrary1.A<IEnumerable<int>>()
.Handle(new List<int> { 1, 2, 3, 4 } as IEnumerable<int>);
}
异常详情:
System.InvalidOperationException:不能对 ContainsGenericParameters 为 true 的类型或方法执行后期绑定操作。
我在 Windows 7 上使用 Visual Studio 2013 preview express 桌面。
1:如何使这种方法起作用?
2:泛型在这里真的是正确的做法吗?如果不是,建议?
***答案详情****
正确的实现是只使用 IEnumerable [non-generic] 来做到这一点:
public class A<T>
{
public void Handle(object payload)
{
var enumerable = payload as IEnumerable;
if(enumerable != null)
{
//do work on enumerable
}
}
}
啊,C# 作为在职培训的缺点。所有的痛点都是由于需要一个通用版本的 IEnumerable,这不是必需的 - 只是认为这是因为我不知道非通用形式。