2010-09-20 67 views
1

我正在与该消息一个InvalidOperationException调用扩展方法:错误使用反射

“操作不能在类型或方法针对ContainsGenericParameters为真进行后期绑定”

以下是代码的相关部分:

// Gets the entity type of the table to update. 
Type entityType = Jobs.GetType(syncSettings.TableToUpdate); 

// Creates a generic list with the same type to hold the records to update. 
Type listType = typeof(List<>).MakeGenericType(entityType); 
object recordsToUpdate = Activator.CreateInstance(listType); 

// Fills the list recordsToUpdate... 
// A few lines below, I try to call the extension method ElementAt: 
MethodInfo elementAtMethod = typeof(Enumerable).GetMethod("ElementAt", BindingFlags.Static | BindingFlags.Public); 
elementAtMethod.MakeGenericMethod(entityType); 

object record = elementAtMethod.Invoke(
            recordsToUpdate, 
            new object[] { recordsToUpdate, recordIndex }); 

在我的最后一个动作,上述异常被抛出。我究竟做错了什么?这个错误是什么意思?

我一直在调查,看来方法参数类型T仍然是通用的。这就是为什么ContainsGenericParameters是真的。如何将参数设置为entityType?

回答

2

简单地说,你还没有抓到的MakeGenericMethod结果(它返回一个不同MethodInfo代表关闭法)

elementAtMethod = elementAtMethod.MakeGenericMethod(entityType); 

不过,我可能会建议,在大多数情况下,更容易使用非通用IList,回退到非泛型IEnumerable(反射和仿制药不是好朋友):

IList list = recordsToUpdate as IList; 
if(list != null) return list[recordIndex]; 
// fallback to IEnumerable 
if(recordIndex < 0) throw new IndexOutOfRangeException(); 
IEnumerable enumerable = (IEnumerable)recordsToUpdate; 
foreach (object item in enumerable) { 
    if (recordIndex-- == 0) return item; 
} 
throw new IndexOutOfRangeException(); 

(注意,您不必使用后备代码,因为您总是使用List<T>,它实现了IList

+0

正是!它是有道理的,因为MakeGenericMethod方法返回MethodInfo而不是void。谢谢@Marc Gravell! – 2010-09-20 10:25:59

+1

@Fabio - 请参阅我的观点'IList';反射/泛型的方法是**,很多**比仅仅投射到“IList”更慢** – 2010-09-20 10:27:40

+0

是的,我意识到反射非常缓慢,但我被告知这不是一个问题,因为我写的方法是仅用于辅助角色。我所做的目标是它变得通用并且无论发生什么变化都能继续工作,但是你所说的话对我来说是完全合理的,并且对此表示感谢。我一定会考虑到它。感谢您的解决方案和最佳选择。你救了我的一天! – 2010-09-20 12:59:06