2010-09-20 62 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