sl3dg3
sl3dg3

Reputation: 5180

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?

Upvotes: 5

Views: 6052

Answers (4)

Manish Basantani
Manish Basantani

Reputation: 17499

This works:

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

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

There are some errors in your code, as following:

  • You need to call GetMethod(...) on the type object of your generic class (not on instance).
  • getAllMethod.Invoke(...) requires the instance of the generic class you have created using Activator.

Upvotes: 1

Samuel Slade
Samuel Slade

Reputation: 8613

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

Upvotes: 1

Peter Monks
Peter Monks

Reputation: 4389

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

Upvotes: 7

Chris Shain
Chris Shain

Reputation: 51319

If this is how you are using it, why are you bothering to make MyClass generic? This would be significantly faster:

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

and then just call

var myObject = new MyClass();
var myList = myObject.GetAll();

Upvotes: 0

Related Questions