使用基于参数的反射获取正确的重载方法

Fetch correct overload method with Reflection based on arguments

假设我有一个方法有很多重载,例如 Console.WriteLine,我想通过反射获取它。我有一个 dynamicx 并想获取与 x 类型最相关的方法,如下所示:

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)]

据我所知,只有知道方法的参数类型才能获取方法,否则会抛出异常:

> 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)]

如何实现上面演示的 GetMethodFromParams 方法?我的一个想法是使用 Type.GetType(...).GetMethods() 方法并根据与 x 的类型相比的参数类型过滤结果,但这可能很难处理协方差和逆变。

事实证明,你可以简单地使用 x.GetType() 来获取 x 的类型并将其作为数组元素传递给 GetMethod 并且它工作得很好,即使对于协变和逆变.这意味着您可以这样实现:

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