private static MethodRecognitionResult TryCallMethod(MethodInfo method, Type[] typeArguments, Expression[] positionalArguments, IDictionary <string, Expression> namedArguments) { var parameters = method.GetParameters(); int castCount = 0; if (parameters.Length < positionalArguments.Length) { return(null); } var args = new Expression[parameters.Length]; Array.Copy(positionalArguments, args, positionalArguments.Length); int namedArgCount = 0; for (int i = positionalArguments.Length; i < args.Length; i++) { if (namedArguments?.ContainsKey(parameters[i].Name) == true) { args[i] = namedArguments[parameters[i].Name]; namedArgCount++; } else if (parameters[i].HasDefaultValue) { castCount++; args[i] = Expression.Constant(parameters[i].DefaultValue, parameters[i].ParameterType); } else { return(null); } } // some named arguments were not used if (namedArguments != null && namedArgCount != namedArguments.Count) { return(null); } int automaticTypeArgs = 0; // resolve generic parameters if (method.ContainsGenericParameters) { var typeArgs = new Type[method.GetGenericArguments().Length]; if (typeArguments != null) { if (typeArguments.Length > typeArgs.Length) { return(null); } Array.Copy(typeArguments, typeArgs, typeArgs.Length); } for (int i = 0; i < typeArgs.Length; i++) { if (typeArgs[i] == null) { // try to resolve from arguments var arg = Array.FindIndex(parameters, p => p.ParameterType.IsGenericParameter && p.ParameterType.GenericParameterPosition == i); automaticTypeArgs++; if (arg >= 0) { typeArgs[i] = args[arg].Type; } else { return(null); } } } method = method.MakeGenericMethod(typeArgs); parameters = method.GetParameters(); } else if (typeArguments != null) { return(null); } // cast arguments for (int i = 0; i < args.Length; i++) { var casted = TypeConversion.ImplicitConversion(args[i], parameters[i].ParameterType); if (casted == null) { return(null); } if (casted != args[i]) { castCount++; args[i] = casted; } } return(new MethodRecognitionResult { CastCount = castCount, AutomaticTypeArgCount = automaticTypeArgs, Method = method, Arguments = args }); }
public CastedExpressionBindingProperty ConvertExpressionToType(ParsedExpressionBindingProperty expr, ExpectedTypeBindingProperty expectedType = null) => new CastedExpressionBindingProperty(TypeConversion.ImplicitConversion(expr.Expression, expectedType?.Type ?? typeof(object), throwException: true, allowToString: true));