鉴于课程:
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所属的类型或方法执行 真。
我在Windows 7上使用Visual Studio 2013预览快速桌面。
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的通用版本,这是不需要的 - 只是因为我不知道非泛型形式。
答案 0 :(得分:0)
您的GetFirstGenericArgument()
错了
调用GetGenericTypeDefinition()
将返回基础开放泛型类型
它的类型参数是T
相反,您应该编写t.GetGenericArguments()[0]
,它将获得封闭类型的泛型类型参数的值。
没有;你的代码没有任何意义。
你究竟想做什么?
我怀疑你真的想写
public class CollectionHandler<T> {
public void Handle(IEnumerable<T> collection) {
// Look ma, no reflection!
}
}
答案 1 :(得分:0)
当您收到HandleIEnumerable<U>
的实例且U从T继承时,您似乎想要调用方法IEnumerable<T>
。
通过指定U应该从T:
继承,你可以在没有反射的情况下完成 private void HandleIEnumerable<U>(IEnumerable<U> payload) where U :T
{
...
}
在你的Handle方法中:
public void Handle(object payload)
{
if(IsEnumerable(payload))
{
HandleIEnumerable((IEnumerable<U>)payload);
}
}