public static IEnumerable <XamlMember> GetSortedConstructorArguments(this XamlType type, IList <object> contents = null) { var constructors = type.UnderlyingType.GetTypeInfo().GetConstructors(); if (contents != null && contents.Count > 0) { var context = type.SchemaContext; // find constructor that matches content type directly first, then by ones that can be converted by type var constructorArguments = FindConstructorArguments(context, constructors, contents, (type1, type2) => type1.UnderlyingType.GetTypeInfo().IsAssignableFrom(type2.UnderlyingType.GetTypeInfo())) ?? FindConstructorArguments(context, constructors, contents, (type1, type2) => type1.CanConvertFrom(type2)); if (constructorArguments != null) { return(constructorArguments); } } // find constructor based on ConstructorArgumentAttribute var args = type.GetConstructorArguments(); foreach (var ci in constructors) { var pis = ci.GetParameters(); if (args.Count != pis.Length) { continue; } bool mismatch = false; foreach (var pi in pis) { mismatch |= args.All(a => a.ConstructorArgumentName() != pi.Name); } if (mismatch) { continue; } return(args.OrderBy(c => pis.FindParameterWithName(c.ConstructorArgumentName()).Position)); } return(null); }
public static IEnumerable <XamlMember> GetSortedConstructorArguments(this XamlType type, IList <object> contents = null) { var constructors = type.UnderlyingType.GetTypeInfo().GetConstructors(); if (contents != null && contents.Count > 0) { // find constructor based on supplied parameters foreach (var constructor in constructors) { var parameters = constructor.GetParameters(); if (contents.Count > parameters.Length) { continue; } bool mismatch = false; for (int i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; if (i >= contents.Count) { // allow parameters with a default value to be omitted mismatch = !parameter.HasDefaultValue(); if (mismatch) { break; } continue; } // check if the parameter value can be assigned to the required type var posParameter = contents[i]; var paramXamlType = type.SchemaContext.GetXamlType(parameter.ParameterType); // check if type input type can be converted to the parameter type var inputType = posParameter == null ? XamlLanguage.Null : type.SchemaContext.GetXamlType(posParameter.GetType()); mismatch = !paramXamlType.CanConvertFrom(inputType); if (mismatch) { break; } } if (mismatch) { continue; } // matches constructor arguments return(constructor .GetParameters() .Select(p => type.SchemaContext.GetParameter(p))); } } // find constructor based on ConstructorArgumentAttribute var args = type.GetConstructorArguments(); foreach (var ci in constructors) { var pis = ci.GetParameters(); if (args.Count != pis.Length) { continue; } bool mismatch = false; foreach (var pi in pis) { for (int i = 0; i < args.Count; i++) { mismatch |= args.All(a => a.ConstructorArgumentName() != pi.Name); } } if (mismatch) { continue; } return(args.OrderBy(c => pis.FindParameterWithName(c.ConstructorArgumentName()).Position)); } return(null); }