ConstructorData GetBestMatch(IEnumerable<ConstructorInfo> constructors, Arguments args, Dictionary<ConstructorInfo, IList<ParameterInfo>> unresolved) { var ctors = constructors.Select(c => new ConstructorMatchData { Constructor = c, Parameters = c.GetParameters().ToList(), ParameterDelta = c.GetParameters().Count() - args.Count(), /* negative number here is most likely (and wanted!) */ MatchLength = 0, Score = 0 }); foreach (var ctor in ctors) { for (var i = 0; i < Math.Min(ctor.Parameters.Count(), args.Count()); i++) { if (ctor.Parameters[i].Name != args[i].Name || ctor.Parameters[i].ParameterType != args[i].Value.GetType()) { break; } ctor.MatchLength = ctor.MatchLength + 1; } } foreach (var ctor in ctors) { ctor.Score = ctor.MatchLength + ctor.ParameterDelta; } //check if the top item has a unique score var best = ctors.Where(c => c.Score == ctors.OrderBy(t => t.Score).First().Score); if (best.Count() == 1) { return new ConstructorData(best.First().Constructor, args.FilteredFor(best.First().Constructor)); } //apply the delta again to try and distinct the matches foreach (var ctor in ctors) { ctor.Score += ctor.ParameterDelta; } //check if the top item has a unique score best = ctors.Where(c => c.Score == ctors.OrderBy(t => t.Score).First().Score); if (best.Count() == 1) { return new ConstructorData(best.First().Constructor, args.FilteredFor(best.First().Constructor)); } throw new ConstructorException(); }