Use Reflection to call generic method on object instance with signature: SomeObject.SomeGenericInstanceMethod<T>(T argument)

13,489

Solution 1

You do it exactly the same way.

When you call MethodInfo.Invoke, you pass all the arguments in an object[] anyway, so it's not like you have to know the types at compile time.

Sample:

using System;
using System.Reflection;

class Test
{
    public static void Foo<T>(T item)
    {
        Console.WriteLine("{0}: {1}", typeof(T), item);
    }

    static void CallByReflection(string name, Type typeArg,
                                 object value)
    {
        // Just for simplicity, assume it's public etc
        MethodInfo method = typeof(Test).GetMethod(name);
        MethodInfo generic = method.MakeGenericMethod(typeArg);
        generic.Invoke(null, new object[] { value });
    }

    static void Main()
    {
        CallByReflection("Foo", typeof(object), "actually a string");
        CallByReflection("Foo", typeof(string), "still a string");
        // This would throw an exception
        // CallByReflection("Foo", typeof(int), "oops");
    }
}

Solution 2

You do it exactly the same way, but pass an instance of your object:

typeof (SomeObject).GetMethod(
       "SomeGenericInstanceMethod", 
        yourObject.GetType())  
                 // Or typeof(TheClass), 
                 // or typeof(T) if you're in a generic method
   .MakeGenericMethod(typeof(GenericParameter))

The MakeGenericMethod method only requires you to specify the generic type parameters, not the method's arguments.

You'd pass the arguments in later, when you call the method. However, at this point, they're passing as object, so it again doesn't matter.

Share:
13,489
smartcaveman
Author by

smartcaveman

Does software exist? https://www.codementor.io/smartcaveman

Updated on June 05, 2022

Comments

  • smartcaveman
    smartcaveman almost 2 years

    How do I call SomeObject.SomeGenericInstanceMethod<T>(T arg) ?

    There are a few posts about calling generic methods, but not quite like this one. The problem is that the method argument parameter is constrained to the generic parameter.

    I know that if the signature were instead

    SomeObject.SomeGenericInstanceMethod<T>(string arg)

    then I could get the MethodInfo with

    typeof (SomeObject).GetMethod("SomeGenericInstanceMethod", new Type[]{typeof (string)}).MakeGenericMethod(typeof(GenericParameter))

    So, How do I go about getting the MethodInfo when the regular arguments are of a generic type? Thanks!

    Also, there may or may not be type constrains on the generic parameter.

  • smartcaveman
    smartcaveman over 13 years
    Will this still work if there are multiple overloads for the method named "name"?
  • Jon Skeet
    Jon Skeet over 13 years
    @smartcaveman: No, you'd need to work out which one to call. Calling GetMethod(string, Type[]) can get quite tricky when the parameter types are generic - I usually use GetMethods in conjunction with a LINQ query to find the right method.
  • Jon Skeet
    Jon Skeet over 13 years
    Note that the GetMethod call may fail if yourObject is a subtype of the required one, as in my first example. The subtype may not satisfy the constraints - for example, consider Foo<T>(T item) where T : new() called as Foo<object>("hello"). We don't want to call Foo<string>("hello") as string doesn't have a parameterless constructor.
  • smartcaveman
    smartcaveman over 13 years
    Something like: typeof(Test).GetMethods(BindingFlags.Instance).Where(x=>x.Is‌​GenericMethodDefinit‌​ion & x.Name==name) ?
  • Jon Skeet
    Jon Skeet over 13 years
    @smartcaveman: Well that wouldn't help if there were two generic methods with the same name. Basically I can't help you much here, because I don't know how you want to be able to identify the right method. Work out how you'd tell them apart manually, and write a query for it.
  • smartcaveman
    smartcaveman over 13 years
    How do you determine that a ParameterInfo is generic?
  • Jon Skeet
    Jon Skeet over 13 years
    @smartcaveman: Try ParameterInfo.ParameterType.IsGenericType.
  • smartcaveman
    smartcaveman over 13 years
    Thanks... I realized that was a bit of a different question, so.. stackoverflow.com/questions/4738826/…