我不确定您为什么要这样做:为什么不调用该方法让编译器的重载解析算法来解决这个问题?
无论如何,作为一个有趣的小练习(我今天很无聊),您可以构建类似于以下内容的东西(有 dynamic 我不确定是否有可能有用的场景):
public class OverloadDelegateList
{
readonly object target;
readonly string methodName;
List<InvokableMethod> methods;
public OverloadDelegateList(Delegate firstOverload)
{
Debug.Assert(firstOverload != null);
this.methods = new List<InvokableMethod>();
this.target = firstOverload.Target;
this.methodName = firstOverload.Method.Name;
AddOverload(firstOverload);
}
public IEnumerable<InvokableMethod> InvokableMethods
{
get { return this.methods; }
}
public void AddOverload(Delegate d)
{
Debug.Assert(d != null);
if (!Object.ReferenceEquals(d.Target, target))
throw new ArgumentException();
if (d.Method.Name != this.methodName)
throw new ArgumentException();
this.methods.Add(new InvokableMethod(d, (from p in d.Method.GetParameters() select p.ParameterType).ToArray()));
}
public object DynamicInvoke(params object[] args)
{
var signature = new MethodSignature((from a in args select a.GetType()).ToArray());
var overload = this.methods.FirstOrDefault(m => m.Signature.Equals(signature));
if (overload == null)
throw new ArgumentException();
return overload.InvokableOverload.DynamicInvoke(args);
}
}
public class InvokableMethod
{
readonly MethodSignature signature;
readonly Delegate invokableMethod;
public InvokableMethod(Delegate invokableMethod, params Type[] types)
:this(invokableMethod, new MethodSignature(types))
{
}
public InvokableMethod(Delegate invokableMethod, MethodSignature signature)
{
Debug.Assert(invokableMethod != null);
this.invokableMethod = invokableMethod;
this.signature =signature;
}
public Delegate InvokableOverload { get { return this.invokableMethod; } }
public MethodSignature Signature { get { return this.signature; } }
}
public class MethodSignature: IEquatable<MethodSignature>
{
readonly List<Type> signature;
public MethodSignature(params Type[] types)
{
this.signature = types.ToList();
}
public IEnumerable<Type> Signature { get { return this.signature; } }
public override bool Equals(object obj)
{
return this.Equals(obj as MethodSignature);
}
public bool Equals(MethodSignature other)
{
if (object.ReferenceEquals(other, null))
return false;
if (other.signature.Count != this.signature.Count)
return false;
for (int i = 0; i < this.signature.Count; ++i)
{
if (this.signature[i] != other.signature[i])
return false;
}
return true;
}
public override int GetHashCode()
{
unchecked
{
int hash = 0;
if (this.signature != null)
{
foreach (var t in this.signature)
{
hash ^= t.GetHashCode();
}
}
return hash;
}
}
}
您可以按如下方式使用它:
考虑以下类 Foo 为方法 Bar 实现 5 种不同的重载:
public class Foo
{
public void Bar() { Console.WriteLine("Bar() called: {0}", string.Empty); }
public void Bar(int i) { Console.WriteLine("Bar(int) called: {0}", i); }
public void Bar(double d) { Console.WriteLine("Bar(double) called: {0:N4}", d); }
public void Bar(int i, string s) { Console.WriteLine("Bar(int, string) called: {0} & {1}", i, s); }
public void Bar(double d, string s) { Console.WriteLine("Bar(double, string) called: {0:N4}, {1}", d, s); }
}
您可以建立一个列表,其中包含Foo.Bar() 重载的所有信息,如下所示:
var foo = new Foo();
var overloads = new OverloadDelegateList(new Action(foo.Bar));
overloads.AddOverload(new Action<int>(foo.Bar));
overloads.AddOverload(new Action<double>(foo.Bar));
overloads.AddOverload(new Action<int, string>(foo.Bar));
overloads.AddOverload(new Action<double, string>(foo.Bar));
现在您可以根据参数的运行时数量和类型动态调用正确的重载:
//We want to call Bar overload with one argument.
object arg1 = 1d;
overloads.DynamicInvoke(arg1);
//We want to call Bar overload with two arguments.
object arg2 = "s";
overloads.DynamicInvoke(arg1, arg2);
请注意,要使此解决方案起作用,您需要静态了解foo(被调用者)。如果您对被调用者没有静态知识,那么您也需要使用Reflection 来找出可能的重载。