Let's say I have a class as follows:
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; } }
Now, if I try to use this in code, I use something like this:
object[] list = new object[] { "a", new object[0], "c", "d" }; Assert.AreEqual(7, list.Select((a)=>((int)new AcceptMethods().Accept((dynamic)a))).Sum());
The reason this is 7 is because overload resolution prefers [ IList<object> ] over [ IEnumerable<object> ] and [ object ], but because [ string , int=default ] takes precedence over [ object ] .
In my scenario, I would like to get the best matching overload using reflection. In other words: "best" is defined as "C # overload resolution." For instance:.
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);
While the sketch I script has only 1 parameter, the solution I'm looking for can have several parameters.
Update 1 :
Since I received a comment that this is too complicated for SO due to difficulties with implementing overload resolution (which I am well aware), I feel apt to send updates. To give my argument of some power, this was my first attempt, which uses the default .NET middleware, which handles overload resolution:
private MethodBase GetBestMatching(IEnumerable<MethodInfo> methods, Type[] parameters) { return Type.DefaultBinder.SelectMethod(BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod, methods.ToArray(), parameters, null); }
This version already seems to make simple overload resolution correct, but does not work with additional parameters. Since .NET afaik works with type binding, as shown here, I believe that the solution can be implemented quite easily.