Search code examples
c#system.reflectionmethodinfo

Get RuntimeMethodInfo from generic overloaded methods in non-generic static class


I try to get runtime method infoes in static class. I have four static method inside the class and each name is equal, also parameter name is equal. The only difference is their types. One of four method has string parameter so it is easy to get method info. However the others don't working. I find several advice but that are not working.

All test code is here.

class Program {
    static void Main(string[] args) {
        //ok
        var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
        //not working
        var dictMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(Dictionary<,>) });
        //not working
        var genericMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(object) });
        //not working
        var listMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(List<>) });


        //not working
        var res = typeof(TestClass)
        .GetRuntimeMethods()
        .Where(x => x.Name.Equals("TestMethod"))
        .Select(m => new { Method = m, Parameters = m.GetParameters() })
        .FirstOrDefault(p =>
            p.Parameters.Length == 1
        && p.Parameters[0].ParameterType.IsGenericType
        && p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(ICollection<>)
        );

    }
}


public static class TestClass {
    public static bool TestMethod(string item) {
        return true;
    }

    public static bool TestMethod<TKey, TValue>(Dictionary<TKey, TValue> item) {
        return true;
    }

    public static bool TestMethod<T>(T item) {
        return true;
    }

    public static bool TestMethod<T>(List<T> item) {
        return true;
    }
}

Solution

  • If you are using .net core 2.1 or greater, you can use Type.MakeGenericMethodParameter to let you refer to a generic parameter of a method. You can use that to create a generic type argument that will work with GetMethod (not available for GetRuntimeMethod).

    var stringMethodInfo = typeof(TestClass).GetRuntimeMethod("TestMethod", new[] { typeof(string) });
    Type[] dictionaryTypeParameters = { typeof(Dictionary<,>).MakeGenericType(Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(1)) };
    MethodInfo dictMethodInfo = typeof(TestClass).GetMethod("TestMethod", 2, dictionaryTypeParameters);
    MethodInfo listMethodInfo = typeof(TestClass).GetMethod("TestMethod", 1, new[] { typeof(List<>).MakeGenericType(Type.MakeGenericMethodParameter(0)) });
    MethodInfo genericMethodInfo = typeof(TestClass).GetMethod("TestMethod", 1, new[] { Type.MakeGenericMethodParameter(0) });
    

    Some interesting reading on the topic here.