5

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?

sl3dg3
  • 5,026
  • 12
  • 50
  • 74
  • Where did `baseRepo` come from in the last line? Shouldn't it be `myClassInstance`? – Damien_The_Unbeliever Jan 27 '12 at 15:51
  • Your sample code must have a bug in this line: MethodInfo getAllMethod = myClassInstance.GetMethod("GetAll", new Type[] {}); – usr Jan 27 '12 at 15:52
  • Yes, OP probably used ``myClassType`` there instead of ``constructed``. After I corrected that, it worked for me. – Jacek Gorgoń Jan 27 '12 at 15:53
  • Example here: http://stackoverflow.com/questions/232535/how-to-use-reflection-to-call-generic-method – eouw0o83hf Jan 27 '12 at 15:53
  • Sorry for the code-errors, happend from simplifying it... fixed that. – sl3dg3 Jan 27 '12 at 15:58
  • Hopefully it's a lesson for the future - if you're going to simplify the example, make sure it compiles and gives the same problem - if it does, great. If it *doesn't*, greater still - you're isolating the difference between your example and your real code, and may be able to solve the problem entirely. – Damien_The_Unbeliever Jan 27 '12 at 19:30
  • possible duplicate of [Setting generic type at runtime](http://stackoverflow.com/questions/2604743/setting-generic-type-at-runtime) – nawfal Jan 17 '14 at 15:27

4 Answers4

7

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); 
Peter Monks
  • 4,219
  • 2
  • 22
  • 38
  • Thx - it was a silly mistake... `constructed.GetMethod("GetAll");` is correct of course, or in my case `myClassInstance.GetMethod("GetAll", new Type[] {});` – sl3dg3 Jan 27 '12 at 16:08
1

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);
Samuel Slade
  • 8,405
  • 6
  • 33
  • 55
1

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.
Samuel Slade
  • 8,405
  • 6
  • 33
  • 55
Manish Basantani
  • 16,931
  • 22
  • 71
  • 103
0

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();
Chris Shain
  • 50,833
  • 6
  • 93
  • 125
  • 1
    My guess would be that making it of Type object was just for the example, to make it as easy to understand as possible – eouw0o83hf Jan 27 '12 at 15:48
  • 1
    Exactly: It is a simplified example. There is good reason why it is like that and why I have to use reflection on an other place. – sl3dg3 Jan 27 '12 at 15:52