如何以编程方式在 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)
.
注意:方法GetMethod
和GetMethods
都不符合我的目的。他们都不做任何重载决议。在 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
在我们可能不希望工作的情况下进行重载解析。
当 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)
.
注意:方法GetMethod
和GetMethods
都不符合我的目的。他们都不做任何重载决议。在 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
在我们可能不希望工作的情况下进行重载解析。