C# 在C中调用泛型类型的泛型方法的后期绑定异常#
鉴于班级:C# 在C中调用泛型类型的泛型方法的后期绑定异常#,c#,generics,reflection,C#,Generics,Reflection,鉴于班级: public class A<T> { public void Handle(object payload) { if(IsEnumerable(payload)) //assume this works { var closedMethod = GetType() .GetMethod( "HandleIEnumerable",
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];
}
}
公共A类
{
公共无效句柄(对象有效负载)
{
if(IsEnumerable(payload))//假设这是可行的
{
var closedMethod=GetType()
.GetMethod(
“可枚举的”,
BindingFlags.NonPublic | BindingFlags.Instance)
.MakeGenericMethod(
GetFirstGenericArgument(typeof(T));
封闭法
.调用(
这
null);//调用操作引发的异常
//调试将类型显示为HandleEnumerable[T]
返回;
}
//处理其他事情
}
//这是因为在上面,我无法与“t”交互
//在不使用反射的情况下是不可数的
//跳环
私有void HandleIEnumerable(对象负载)
{
foreach(有效负载中的var元素为IEnumerable)
{
//对元素做些什么
}
}
私有布尔值可计算(对象有效负载)
{
变量类型=类型(T);
返回
type.IsGenericType
&&(type.GetGenericTypeDefinition()==typeof(IEnumerable));
}
私有类型GetFirstGenericArgument(类型t)
{
返回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>);
}
[TestMethod]
public void A_Handle_IEnumerable()
{
新类库1.A()
.Handle(新列表{1,2,3,4}为IEnumerable);
}
例外情况详情:
System.InvalidOperationException:不能执行后期绑定操作
对包含GenericParameters的类型或方法执行
对
我正在Windows 7上使用Visual Studio 2013预览express桌面
1:我如何使这种方法起作用
2:在这里泛型真的是正确的吗?如果不是,建议
***答案详细信息***
正确的实现方法是只使用IEnumerable[非泛型]来实现:
public class A<T>
{
public void Handle(object payload)
{
var enumerable = payload as IEnumerable;
if(enumerable != null)
{
//do work on enumerable
}
}
}
公共A类
{
公共无效句柄(对象有效负载)
{
var enumerable=作为IEnumerable的有效负载;
if(可枚举!=null)
{
//做可枚举的工作
}
}
}
啊,C#as在职培训的缺点。所有的痛点都是因为需要IEnumerable的泛型版本,这是不需要的——只是我认为这是因为我不知道非泛型形式
GetFirstGenericArgument()
错误。调用
GetGenericTypeDefinition()
返回基础的开放泛型类型。它的类型参数是
T
相反,您应该编写
t.GetGenericArguments()[0]
,它将获取关闭类型的泛型类型参数的值你到底想干什么?
我怀疑你真的想写作
public class CollectionHandler<T> {
public void Handle(IEnumerable<T> collection) {
// Look ma, no reflection!
}
}
公共类CollectionHandler{
公共无效句柄(IEnumerable集合){
//看,妈妈,没有反应!
}
}
当您接收到
IEnumerable
的实例且U从T继承时,似乎要调用方法HandleEnumerable
通过指定U应该从T继承,您可以在不进行反射的情况下执行此操作:
private void HandleIEnumerable<U>(IEnumerable<U> payload) where U :T
{
...
}
private void handlei可枚举(IEnumerable payload),其中U:T
{
...
}
在你的处理方法中:
public void Handle(object payload)
{
if(IsEnumerable(payload))
{
HandleIEnumerable((IEnumerable<U>)payload);
}
}
公共无效句柄(对象负载)
{
if(可计算(有效载荷))
{
HandleEnumerable((IEnumerable)有效载荷);
}
}
你想用这段代码做什么?接收一个未知类型的对象,如果它是IEnumerable,则对它进行迭代并执行某些操作,如果它不是IEnumerable,则执行其他操作。我尝试了一些简单得多的方法,但似乎每件事都需要输入IEnumerable,而“something”似乎只能通过反射来获取。这将在哪里以及如何与我的代码挂钩?我试了一下,但无法推断类型。@PatrickV:在看到对您的问题的评论后,您实际上想使用非泛型的System.Collections.IEnumerable
,并完全摆脱泛型。谢谢SLaks,这就成功了。主帖子更新了详细信息。对T没有约束。当且仅当T是IEnumerable时,我想迭代该枚举并做一些事情。但是T也可能是一个字符串,在这种情况下,我不想这样做。