How do I use reflection to call a generic method?

Viewed 328747

What's the best way to call a generic method when the type parameter isn't known at compile time, but instead is obtained dynamically at runtime?

Consider the following sample code - inside the Example() method, what's the most concise way to invoke GenericMethod<T>() using the Type stored in the myType variable?

public class Sample
{
    public void Example(string typeName)
    {
        Type myType = FindType(typeName);

        // What goes here to call GenericMethod<T>()?
        GenericMethod<myType>(); // This doesn't work

        // What changes to call StaticMethod<T>()?
        Sample.StaticMethod<myType>(); // This also doesn't work
    }

    public void GenericMethod<T>()
    {
        // ...
    }

    public static void StaticMethod<T>()
    {
        //...
    }
}
8 Answers

You need to use reflection to get the method to start with, then "construct" it by supplying type arguments with MakeGenericMethod:

MethodInfo method = typeof(Sample).GetMethod(nameof(Sample.GenericMethod));
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);

For a static method, pass null as the first argument to Invoke. That's nothing to do with generic methods - it's just normal reflection.

As noted, a lot of this is simpler as of C# 4 using dynamic - if you can use type inference, of course. It doesn't help in cases where type inference isn't available, such as the exact example in the question.

Inspired by Enigmativity's answer - let's assume you have two (or more) classes, like

public class Bar { }
public class Square { }

and you want to call the method Foo<T> with Bar and Square, which is declared as

public class myClass
{
    public void Foo<T>(T item)
    {
        Console.WriteLine(typeof(T).Name);
    }
}

Then you can implement an Extension method like:

public static class Extension
{
    public static void InvokeFoo<T>(this T t)
    {
        var fooMethod = typeof(myClass).GetMethod("Foo");
        var tType = typeof(T);
        var fooTMethod = fooMethod.MakeGenericMethod(new[] { tType });
        fooTMethod.Invoke(new myClass(), new object[] { t });
    }
}

With this, you can simply invoke Foo like:

var objSquare = new Square();
objSquare.InvokeFoo();

var objBar = new Bar();
objBar.InvokeFoo();

which works for every class. In this case, it will output:

Square
Bar

Related