假设我有一堂课如下:
public class AcceptMethods
{
public int Accept(string s, int k = 1)
{
return 1;
}
public int Accept(object s)
{
return 2;
}
public int Accept(IEnumerable<object> s)
{
return 7;
}
public int Accept(IList<object> s)
{
return 4;
}
}
现在,如果我尝试在代码中使用它,我会使用这样的东西:
object[] list = new object[] { "a", new object[0], "c", "d" };
Assert.AreEqual(7, list.Select((a)=>((int)new AcceptMethods().Accept((dynamic)a))).Sum());
它是 7 的原因是因为重载决议更喜欢 [ IList<object>
] 而不是 [ IEnumerable<object>
] 和 [ object
],并且因为 [ string
, int=default
] 优先于 [ object
]。
在我的场景中,我想使用反射获得最佳匹配的重载。换句话说:“最佳”被定义为“c#重载决议”。例如:
int sum = 0;
foreach (var item in list)
{
var method = GetBestMatching(typeof(AcceptMethods).GetMethods(), item.GetType());
sum += (int)method.Invoke(myObject, new object[]{item});
}
Assert.AreEqual(7, sum);
虽然我绘制的场景只有 1 个参数,但我寻求的解决方案可以有多个参数。
更新 1:
因为我收到一条评论,由于重载解决方案实现的困难(我很清楚),这对 SO 来说太难了,我倾向于发送更新。为了给我的论点一些力量,这是我的第一次尝试,它使用处理重载决议的默认 .NET 绑定器:
private MethodBase GetBestMatching(IEnumerable<MethodInfo> methods, Type[] parameters)
{
return Type.DefaultBinder.SelectMethod(BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
methods.ToArray(), parameters, null);
}
这个版本似乎已经正确地进行了简单的重载解析,但无法使用可选参数。因为 .NET afaik 与我在这里展示的类型绑定一起工作,所以我认为该解决方案可以相当容易地实现。