private Type Match(ArgumentSet arguments) { bool useDefault = arguments.Any(a => a.Value.IsDefault); var matchingTypes = new List <TypeMatch>(); foreach (var type in Types) { object[] customAttributes = type.GetCustomAttributes(typeof(DefaultArgumentsAttribute), false); bool isDefaultArgs = customAttributes.Length > 0; bool isMatch = isDefaultArgs && arguments.Count == 0; var matchingType = new TypeMatch { Type = type }; foreach (var argument in arguments) { if (isDefaultArgs && useDefault && argument.Value.IsDefault) { isMatch = true; argument.Value.IsDefault = true; argument.Value.Value = argument.Key; matchingType.ArgumentMatches++; } else { if (GetPropertyInfo(type, argument.Key) != null) { isMatch = true; matchingType.ArgumentMatches++; } } } if (isMatch) { matchingTypes.Add(matchingType); } } if (matchingTypes.Count == 1) { return(matchingTypes[0].Type); } var matchingTypesInOrder = matchingTypes.OrderByDescending(x => x.ArgumentMatches).ToList(); if (matchingTypes.Count > 1) { if (matchingTypesInOrder[0].ArgumentMatches == matchingTypesInOrder[1].ArgumentMatches) { throw new Exception(string.Format("The arguments [{0}] and [{1}] are non deterministic in respect to the args: {2}", matchingTypesInOrder[0].Type.Name, matchingTypesInOrder[1].Type.Name, arguments)); } } TypeMatch matching = matchingTypesInOrder.FirstOrDefault(); if (matching != null) { return(matching.Type); } return(null); }