How to call generic method with a given Type object?

75,323

Solution 1

Your code sample won't work, because the generic method expects a type identifier, not a an instance of the Type class. You'll have to use reflection to do it:

public class Example {

    public void CallingTest()
    {
        MethodInfo method = typeof (Example).GetMethod("Test");
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

Do keep in mind that this is very brittle, I'd rather suggest finding another pattern to call your method.

Another hacky solution (maybe someone can make it a bit cleaner) would be to use some expression magic:

public class Example {

    public void CallingTest()
    {
        MethodInfo method = GetMethod<Example>(x => x.Test<object>());
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public static MethodInfo GetMethod<T>(Expression<Action<T>> expr)
    {
        return ((MethodCallExpression) expr.Body)
            .Method
            .GetGenericMethodDefinition();
    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

Note passing the 'object' type identifier as a generic type argument in the lambda. Couldn't figure out so quickly how to get around that. Either way, this is compile-time safe I think. It just feels wrong somehow :/

Solution 2

You need to use reflection, unfortunately (for the reasons Jared mentioned). For example:

MethodInfo method = typeof(Foo).GetMethod("MyGenericMethod");
method = method.MakeGenericMethod(t);
method.Invoke(this, new object[0]);

Obviously you'd want more error checking in reality :)


Side note: my local MSDN doesn't specify that the parameter from MakeGenericMethod is a parameter array, so I'd have expected to require:

method = method.MakeGenericMethod(new Type[] { t });

but it seems it is a parameter array in reality, and the online MSDN docs agree. Odd.

Share:
75,323
codymanix
Author by

codymanix

General interests Programming languages in general Especially .NET/C#/LINQ Database systems Low level stuff like C/Assembler Multimedia systems Game programming

Updated on July 08, 2022

Comments

  • codymanix
    codymanix almost 2 years

    I want to call my generic method with a given type object.

    void Foo(Type t)
    {
         MyGenericMethod<t>();
    }
    

    obviously doesn't work.

    How can I make it work?