Invoking with generics using reflection

Sometimes we need to run methods or create types with generic parameters at runtime. For example, situation where the type is not known at compiler time but the method(s) we want to use expect the generic parameter to be supplied.

Let’s take a look at the syntax of various scenarios and you’ll get the idea.

Calling an instance method

So let’s assume we have some code like this

public class Runner
{
   public T Create<T>()
   {
      // do something
      return default(T);
   }
}

and we want to invoke this at runtime with an “unknown” (i.e. discovered at runtime) type. We can write something like this

object unknown = CreateType(); // generates some type at runtime

var runner = new Runner();

typeof (Runner).
   GetMethod("Create").
   MakeGenericMethod(unknown.GetType()).
   Invoke(runner, null);

This code would also work if the Create method was a static.

Note: we can ofcourse use typeof(Runner) or runner.GetType() in the above depending upon your preference or use.

Next up, let’s look at the same code but where we need to also pass the method a generic parameter.

public class Runner
{
   public T Create<T>(T type)
   {
      // do something
      return type;
   }
}

So the only real difference here is that we also need to pass the type into the method, a simple addition of the parameters to the invoke will allow this to work, here’s the code

object unknown = CreateType(); // generates some type at runtime

var runner = new Runner();

typeof(Runner).
   GetMethod("Create").
   MakeGenericMethod(unknown.GetType()).
   Invoke(runner, new []{ unknown });

Calling methods on a static class or extension methods

As you will know, extension methods are really just static classes with syntactic sugar to allow them to appear like instance methods, so the procedure for invoking them is the same as the normal static classed, but we’ll cover examples here all the same.

Let’s first look at a static class

public static class Runner
{
   public static T Create<T>()
   {
      // do something
      return default(T);
   }
}

The only real difference to the code for the instance method on a non-static class is that we do not pass a instance to the first parameter of the invoke method, like this

object unknown = CreateType(); // generates some type at runtime

typeof(Runner).
   GetMethod("Create").
   MakeGenericMethod(unknown.GetType()).
   Invoke(null, null);

As extension methods expect a “this” argument, they’re no different to the above code, expect that we need to ensure the first argument is the instance of an object

public static class Runner
{
   public static T Create<T>(this DoSomething doSomething)
   {
      // do something
      return default(T);
   }
}

public class DoSomething
{		
}

So this assumes Create is an extension method for the class, DoSomething. To invoke this Create method we can simply write

object unknown = CreateType(); // generates some type at runtime

var doSomething = new DoSomething();

typeof(Runner).
   GetMethod("Create").
   MakeGenericMethod(unknown.GetType()).
   Invoke(null, new object[]{ doSomething });

Classes with generic parameters

So now let’s move the generic parameter onto the class itself. We’ll begin by looking at static classes

public static class Runner<T>
{
   public static T Create()
   {
      // do something
      return default(T);
   }
}

So now we need to make the generic on the type not the method. We get this

typeof(Runner<>).
   MakeGenericType(unknown.GetType()).
   GetMethod("Create").
   Invoke(null, null);

Notice how the MakeGenericType is used to generate our generic class and the syntax of the typeof.

Obviously we might wish to create non-static classes with generic parameters as well, something like this

public class Runner<T>
{
   public T Create()
   {
      // do something
      return default(T);
   }
}

ofcourse we can’t simply create an instance to this class and use the same techniques of previous because the type of the generic parameter is not known, so we need to create an instance of this class via reflection then invoke the method – this can be accomplished with

var genericType = typeof (Runner<>).
	MakeGenericType(unknown.GetType());

var runner = Activator.CreateInstance(genericType);

genericType
	.GetMethod("Create").
	Invoke(runner, null);

In the above we need to use the genericType twice, so we store it in a local variable. The first time we use it is with Activator.CreateInstance this creates an instance of the class with a generic parameter. Next we use the same type but with the GetMethod call and ofcourse pass the instance variable into Invoke.

What about when we have more than one generic parameter

So what if we had something like this

public class Runner<T1, T2>
{
   public T1 Create()
   {
      var t2 = default(T2);
      // do something
      return default(T1);
   }
}

Obviously this is assuming T2 actually does something of use in our code.

All of the previous sample code will work, the difference is that we declare the typeof(Runner<>) as typeof(Runner<,>) and need to pass the extra parameters in the MakeGenericType method, for example

var genericType = typeof (Runner<,>).
   MakeGenericType(unknown1.GetType(), unknown2.GetType());

var runner = Activator.CreateInstance(genericType);

genericType
   .GetMethod("Create").
   Invoke(runner, null);