Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reflection: Calling Method with generic list as a result

I have the following example-class:

public class MyClass<T>
{
    public IList<T> GetAll()
    {
        return null; // of course, something more meaningfull happens here...
    }
}

And I would like to invoke GetAll with reflection:

Type myClassType = typeof(MyClass<>);
Type[] typeArgs = { typeof(object) };
Type constructed = myClassType.MakeGenericType(typeArgs);
var myClassInstance = Activator.CreateInstance(constructed);

MethodInfo getAllMethod = myClassType.GetMethod("GetAll", new Type[] {});
object magicValue = getAllMethod.Invoke(myClassInstance, null);

This results in (on last line of above code):

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

Okay, second try:

MethodInfo getAllMethod = myClassType.GetMethod("GetAll", new Type[] {});
getAllMethod = getAllMethod.MakeGenericMethod(typeof(object));
object magicValue = getAllMethod.Invoke(myClassInstance, null);

This results in (on second last line of above code):

System.Collections.Generic.IList`1[T] GetAll() is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.

What am I doing wrong here?

like image 879
sl3dg3 Avatar asked Jan 27 '12 15:01

sl3dg3


People also ask

How do I use reflection to call a generic method?

The first step to dynamically invoking a generic method with reflection is to use reflection to get access to the MethodInfo of the generic method. To do that simply do this: var methodInfo = typeof(ClassWithGenericMethod). GetMethod("MethodName");

How do you call a method of a generic type?

Then, we construct a generic version of it by calling the MakeGenericMethod() with the target type. To invoke this generic method, we need two things: an instance of the owner class of the method and the necessary arguments for the parameters of the original method in form of an object array.

Do generics use reflection?

Because the Common Language Runtime (CLR) has access to generic type information at run time, you can use reflection to obtain information about generic types in the same way as for non-generic types.


2 Answers

I've tried this and it works:

// Create generic type
Type myClassType = typeof(MyClass<>);
Type[] typeArgs = { typeof(object) };   
Type constructed = myClassType.MakeGenericType(typeArgs);

// Create instance of generic type
var myClassInstance = Activator.CreateInstance(constructed);    

// Find GetAll() method and invoke
MethodInfo getAllMethod = constructed.GetMethod("GetAll");
object result = getAllMethod.Invoke(myClassInstance, null); 
like image 183
Peter Monks Avatar answered Oct 13 '22 07:10

Peter Monks


I've noticed (not sure if it's just an error in your sample) that there is a problem with your code. myClassInstance will be of type object and so you cannot call GetMethod(...) on it. I think you may mean to call that on the type instead. Secondly, you are passing baseRepo as the object to invoke the method on - surely you want to invoke the method on the instantiation of the type - in this case, the variable myClassInstance?

If you modify your code this way, you should have something like the below code (which, when testing, works):

Type classType = typeof(MyClass<>);
Type[] typeArgs = { typeof(object) };
Type fullClassType = classType.MakeGenericType(typeArgs);

var classInstance = Activator.CreateInstance(fullClassType);

MethodInfo method = fullClassType.GetMethod("GetAll", new Type[0]);
object result = method.Invoke(classInstance, null);
like image 30
Samuel Slade Avatar answered Oct 13 '22 08:10

Samuel Slade