如何以编程方式在 C# 中执行方法重载解析?

How can I programmatically do method overload resolution in C#?

当 C# 编译器解释方法调用时,它必须使用(静态)参数类型来确定实际调用的重载。我希望能够以编程方式执行此操作。

如果我有一个方法的名称(string)、声明它的类型(System.Type 的一个实例)以及我希望能够使用的参数类型列表调用标准库函数并返回一个 MethodInfo 对象,表示 C# 编译器将选择调用的方法。

例如,如果我有

class MyClass {
  public void myFunc(BaseClass bc) {};
  public void myFunc(DerivedClass dc) {};
}

然后我想要 System.Type

上的虚构函数 GetOverloadedMethod
MethodInfo methodToInvoke
  = typeof(MyClass).GetOverloadedMethod("myFunc", new System.Type[] {typeof(BaseClass)});

在这种情况下 methodToInvoke 应该是 public void myFunc(BaseClass bc).

注意:方法GetMethodGetMethods 都不符合我的目的。他们都不做任何重载决议。在 GetMethod 的情况下,它只有 return 完全匹配。如果你给它更多的派生参数,它只会 return 什么都没有。或者你可能很幸运得到一个不提供任何有用信息的歧义异常。

回答

使用 Type.GetMethod(String name, Type[] types) 进行编程重载解析。这是一个例子:

MethodInfo methodToInvoke = typeof(MyClass)
    .GetMethod("myFunc", new System.Type[] { typeof(BaseClass) });

说明

在例子中,methodToInvoke将是myFunc(BaseClass bc)而不是myFunc(DerivedClass dc),因为types数组指定了要获取的方法的参数列表。

From the MSDN documentation,Type.GetMethod(String name, Type[] types)有两个参数:

  • name是要获取的方法名,而
  • types 提供方法参数的顺序、数量和类型。

运行代码

Here is a running fiddle 演示了编程重载解析。

using System;
using System.Reflection;

public static class Program
{
    public static void Main()
    {
        MethodInfo methodToInvoke = typeof(MyClass)
            .GetMethod("myFunc", new System.Type[] { typeof(BaseClass) });

        var result = methodToInvoke
            .Invoke(new MyClass(), new object[] { new BaseClass() });

        Console.WriteLine(result);      
    }

    public class MyClass
    {
        public static string myFunc(BaseClass bc) {
            return "BaseClass";
        }

        public static string myFunc(DerivedClass dc) {
            return "DerivedClass";
        }
    }

    public class BaseClass { }
    public class DerivedClass : BaseClass { }
}

输出为BaseClass

编辑:这很可靠。

GetMethod 解决了采用 params、更派生的 类、委托和接口实现的方法。 This Fiddle demonstrates all of those cases。以下是调用及其检索的内容。

适用于 params

MethodInfo methodToInvoke2 = typeof(MyClass).GetMethod(
        "myFunc",
        new System.Type[] { typeof(Int32[]) });

将解决此方法

public static string myFunc(params int[] i)
{
    return "params";
}

与更多衍生作品一起使用 类

MethodInfo methodToInvoke3 = typeof(MyClass).GetMethod(
    "myFunc", 
    new System.Type[] { typeof(MoreDerivedClass) });

解析一个采用 MoreDerivedClass

的方法
public class BaseClass { }
public class DerivedClass : BaseClass { }
public class MoreDerivedClass : DerivedClass {}

与代表一起工作

MethodInfo methodToInvoke4 = typeof(MyClass).GetMethod(
    "myFunc", 
    new System.Type[] { typeof(MyDelegate) });

... 将检索采用此委托的方法:

public delegate void MyDelegate(string x);

使用接口实现

MethodInfo methodToInvoke5 = typeof(MyClass).GetMethod(
   "myFunc", 
   new System.Type[] { typeof(MyImplementation) });

...成功检索到采用MyImplementation

的方法
public interface IMyInterface {}
public class MyImplementation : IMyInterface {}

因此,它很健壮,我们可以使用 GetMethod 在我们可能不希望工作的情况下进行重载解析。