public static ScoredConstructor GetBestConstructor(Type type, IEnumerable <Type> argumentTypes) { var context = new ConstructorDiscoveryContext(type, argumentTypes); var scored = GetConstructorsByScore(context); return(scored.Where(sc => sc.Score >= 0).OrderByDescending(sc => sc.Score).FirstOrDefault()); }
private static List <ScoredConstructor> GetConstructorsByScore(ConstructorDiscoveryContext context) { var constructors = context.TargetType.GetConstructors(BindingFlags.Public | BindingFlags.Instance); var scoredList = new List <ScoredConstructor>(); foreach (var constructor in constructors) { ScoredConstructor scored = ScoreConstructor(constructor, context); scoredList.Add(scored); } return(scoredList); }
private static ScoredConstructor ScoreConstructor(ConstructorInfo constructor, ConstructorDiscoveryContext context) { if (constructor.IsPrivate) { return(ScoredConstructor.Unusable(constructor)); } // parameters are the defined formal parameters of the constructor // arguments are the values and object references provided by the caller var parameters = constructor.GetParameters(); if (parameters.Length == 0) { return(ScoredConstructor.Parameterless(constructor)); } int score = 0; List <bool> usedArguments = context.ArgumentTypes.Select(t => false).ToList(); var argumentMap = new Dictionary <int, int>(); for (int paramIdx = 0; paramIdx < parameters.Length; paramIdx++) { var parameter = parameters[paramIdx]; int foundScore = -1; var parameterType = parameter.ParameterType; for (int argIdx = 0; argIdx < context.ArgumentTypes.Count; argIdx++) { if (usedArguments[argIdx]) { continue; } var argType = context.ArgumentTypes[argIdx]; foundScore = ScoreTypeMatch(argType, parameterType); if (foundScore >= 0) { usedArguments[argIdx] = true; argumentMap.Add(paramIdx, argIdx); score += foundScore; break; } } if (foundScore < 0) { return(ScoredConstructor.Unusable(constructor)); } } return(new ScoredConstructor(score, constructor, argumentMap)); }