2010-09-20 3 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! –

+1

@Fabio - посмотрите мою точку зрения на 'IList'; подход reflection/generics ** намного, намного медленнее, чем просто приведение к 'IList' –

+0

Да, я знаю, что отражение происходит очень медленно, но мне было поручено, что это не проблема, поскольку методы, которые я пишу, используется только в рабочей роли. Целью того, что я делаю, является то, что она становится родовой и продолжает работать независимо от того, какие изменения, но то, что вы сказали, имеет для меня прекрасный смысл и благодарит вас за это. Я определенно буду учитывать это. Спасибо за ваше решение и лучшую альтернативу. Ты спас мой день! –

Смежные вопросы