Search code examples
c#overloadingsystem.reflection

Fetch correct overload method with Reflection based on arguments


Suppose I have a method with many overloads, such as Console.WriteLine, which I want to fetch via Reflection. I have a dynamic value x and want to fetch the most relevant method for x's type, like this:

var consoleType = Type.GetType("System.Console")

dynamic x = "Foo";
GetMethodFromParams(consoleType, "WriteLine", new[] {x}); // => [Void WriteLine(string)]

x = 3;
GetMethodFromParams(consoleType, "WriteLine", new[] {x}); // => [Void WriteLine(int)]

x = new SomeClass();
GetMethodFromParams(consoleType, "WriteLine", new[] {x}); // => [Void WriteLine(object)]

From what I can see, you can only fetch a method if you know the parameter types of the method, otherwise an exception is thrown:

> Type.GetType("System.Console").GetMethod("WriteLine")
Ambiguous match found.
  + System.RuntimeType.GetMethodImpl(string, System.Reflection.BindingFlags, System.Reflection.Binder, System.Reflection.CallingConventions, System.Type[], System.Reflection.ParameterModifier[])
  + System.Type.GetMethod(string)

> Type.GetType("System.Console").GetMethod("WriteLine", new[] { Type.GetType("System.String") })
[Void WriteLine(System.String)]

How could I implement the GetMethodFromParams method demonstrated above? One idea I had was using the Type.GetType(...).GetMethods() method and filtering through the results based on their parameter types compared to x's type, but this might be tricky to get working with covariance and contravariance.


Solution

  • Turns out, you can simply use x.GetType() to get x's type and pass that as an array element to GetMethod and it works great, even for covariance and contravariance. This means you could implement this like so:

    public static MethodInfo GetMethodFromParams(Type t, string methodName, dynamic[] args)
        => t.GetMethod(methodName,
               args.Select(x => (Type)x.GetType())
                   .ToArray());