tags:

views:

37

answers:

1

I am getting an InvalidOperationException with the message:

"Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true."

The following is the relevant part of the code:

// 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 });

In my last action, the exception mentioned above is thrown. What am I doing wrong? What does this error mean?

I have been investigating and it seems that the method parameter type T is still generic. That's why ContainsGenericParameters is true. How do I set the parameter to the entityType?

+2  A: 

Simply , you haven't caught the result of MakeGenericMethod (it returns a different MethodInfo representing the closed method)

elementAtMethod = elementAtMethod.MakeGenericMethod(entityType);

However, might I suggest that in most cases it is easier to use the non-generic IList, falling back to non-generic IEnumerable (reflection and generics are not good friends):

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();

(note, you won't have to use the fallback code, since you are always using List<T> which implements IList)

Marc Gravell
Exactly! It makes all sense because MakeGenericMethod method returns MethodInfo and not void. Thanks @Marc Gravell!
Fabio Milheiro
@Fabio - please see my point on `IList`; the reflection/generics approach is **much, much** slower than just casting to `IList`
Marc Gravell
Yes, I am aware that reflection is very slow, but I was instructed that this was not a problem since the methods I am writing are used only in the worker role. The goal for what I am doing is that it becomes generic and keeps working no matter what changes, but what you said makes perfect sense to me and thank you for it. I will definitely take it into account. Thanks for your solution and your best alternative. You saved my day!
Fabio Milheiro