public virtual object Execute(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <Type> returnTypes) { var filterLazy = info.GetFilterLazy(); foreach (var type in returnTypes) { try { var result = FunctionCommand.ConvertParam(Content, type, filterLazy); Log.Debug("Converting command result {0} to {1} returns {2}", Content, type, result); return(ResultHelper.ToResult(type, result)); } catch (Exception ex) { Log.Debug(ex, "Converting command result {0} to {1} failed", Content, type); } } throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); }
/// <summary> /// Try to fit the given arguments to the underlying function. /// This function will throw an exception if the parameters can't be applied. /// The parameters that are extracted from the arguments will be returned if they can be applied successfully. /// </summary> /// <param name="info">The current call <see cref="ExecutionInformation"/>.</param> /// <param name="arguments">The arguments that are applied to this function.</param> /// <param name="returnTypes">The possible return types.</param> /// <param name="takenArguments">How many arguments could be set.</param> private object[] FitArguments(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <Type> returnTypes, out int takenArguments) { var parameters = new object[CommandParameter.Length]; var filterLazy = info.GetFilterLazy(); // takenArguments: Index through arguments which have been moved into a parameter // p: Iterate through parameters takenArguments = 0; for (int p = 0; p < parameters.Length; p++) { var arg = CommandParameter[p].Type; switch (CommandParameter[p].Kind) { case ParamKind.SpecialArguments: parameters[p] = arguments; break; case ParamKind.SpecialReturns: parameters[p] = returnTypes; break; case ParamKind.Dependency: if (info.TryGet(arg, out var obj)) { parameters[p] = obj; } else if (CommandParameter[p].Optional) { parameters[p] = null; } else { throw new MissingContextCommandException($"Command '{internCommand.Name}' missing execution context '{arg.Name}'", arg); } break; case ParamKind.NormalCommand: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } parameters[p] = arguments[takenArguments]; takenArguments++; break; case ParamKind.NormalParam: case ParamKind.NormalTailString: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var types = GetTypes(arg); if (CommandParameter[p].Kind == ParamKind.NormalTailString) { types.Insert(0, typeof(TailString)); } var argResultP = arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), types); if (CommandParameter[p].Kind == ParamKind.NormalTailString && argResultP is TailString tailString) { parameters[p] = tailString.Tail; } else { parameters[p] = ConvertParam(UnwrapPrimitive(argResultP), arg, filterLazy); } takenArguments++; break; case ParamKind.NormalArray: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var typeArr = arg.GetElementType(); var args = Array.CreateInstance(typeArr, arguments.Count - takenArguments); for (int i = 0; i < args.Length; i++, takenArguments++) { var argResultA = arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), GetTypes(typeArr)); var convResult = ConvertParam(UnwrapPrimitive(argResultA), typeArr, filterLazy); args.SetValue(convResult, i); } parameters[p] = args; break; default: throw Tools.UnhandledDefault(CommandParameter[p].Kind); } } // Check if we were able to set enough arguments int wantArgumentCount = Math.Min(parameters.Length, RequiredParameters); if (takenArguments < wantArgumentCount && !returnTypes.Contains(typeof(ICommand))) { throw ThrowAtLeastNArguments(wantArgumentCount); } return(parameters); }