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);
        }
Ejemplo n.º 2
0
        /// <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);
        }