Exemplo n.º 1
0
        public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <CommandResultType> returnTypes)
        {
            // Make arguments lazy, we only want to execute them once
            arguments = arguments.Select(c => new LazyCommand(c)).ToArray();
            var parameters = FitArguments(info, arguments, returnTypes, out int availableArguments);

            // Check if we were able to set enough arguments
            int wantArgumentCount = Math.Min(parameters.Length, RequiredParameters);

            if (availableArguments < wantArgumentCount)
            {
                if (returnTypes.Contains(CommandResultType.Command))
                {
                    return(arguments.Count > 0
                                                ? new CommandCommandResult(new AppliedCommand(this, arguments))
                                                : new CommandCommandResult(this));
                }
                throw ThrowAtLeastNArguments(wantArgumentCount);
            }

            if (CommandReturn == typeof(ICommandResult))
            {
                return((ICommandResult)ExecuteFunction(parameters));
            }

            bool   executed = false;
            object result   = null;

            // Take first fitting command result
            foreach (var returnType in returnTypes)
            {
                switch (returnType)
                {
                case CommandResultType.Command:
                    // Return a command if we can take more arguments
                    if (CommandParameter.Any(p => p.type == typeof(string[])) || availableArguments < NormalParameters)
                    {
                        return(new CommandCommandResult(new AppliedCommand(this, arguments)));
                    }
                    break;

                case CommandResultType.Empty:
                    if (!executed)
                    {
                        ExecuteFunction(parameters);
                    }
                    return(EmptyCommandResult.Instance);

                case CommandResultType.String:
                    if (!executed)
                    {
                        result   = ExecuteFunction(parameters);
                        executed = true;
                    }
                    var resultStr = result?.ToString();
                    if (!string.IsNullOrEmpty(resultStr))
                    {
                        return(new StringCommandResult(resultStr));
                    }
                    break;

                case CommandResultType.Json:
                    if (!executed)
                    {
                        result   = ExecuteFunction(parameters);
                        executed = true;
                    }

                    switch (result)
                    {
                    case null: break;

                    case JsonObject jsonResult: return(new JsonCommandResult(jsonResult));

                    default: return(new JsonCommandResult((JsonObject)Activator.CreateInstance(typeof(JsonValue <>).MakeGenericType(result.GetType()), result)));
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            // Try to return an empty string
            if (returnTypes.Contains(CommandResultType.String) && executed)
            {
                return(new StringCommandResult(""));
            }
            throw new CommandException("Couldn't find a proper command result for function " + internCommand.Name, CommandExceptionReason.NoReturnMatch);
        }
Exemplo n.º 2
0
        public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <CommandResultType> returnTypes)
        {
            // Make arguments lazy, we only want to execute them once
            arguments = arguments.Select(c => new LazyCommand(c)).ToArray();
            object[] parameters = FitArguments(info, arguments, returnTypes, out int availableArguments);

            // Check if we were able to set enough arguments
            if (availableArguments < Math.Min(parameters.Length, RequiredParameters))
            {
                if (returnTypes.Contains(CommandResultType.Command))
                {
                    return(arguments.Any()
                                                ? new CommandCommandResult(new AppliedCommand(this, arguments))
                                                : new CommandCommandResult(this));
                }
                throw new CommandException("Not enough arguments for function " + internCommand.Name, CommandExceptionReason.MissingParameter);
            }

            if (CommandReturn == typeof(ICommandResult))
            {
                return((ICommandResult)ExecuteFunction(parameters));
            }

            bool   executed = false;
            object result   = null;

            // Take first fitting command result
            foreach (var returnType in returnTypes)
            {
                switch (returnType)
                {
                case CommandResultType.Command:
                    // Return a command if we can take more arguments
                    if (CommandParameter.Any(p => p == typeof(string[])) || availableArguments < NormalParameters)
                    {
                        return(new CommandCommandResult(new AppliedCommand(this, arguments)));
                    }
                    break;

                case CommandResultType.Empty:
                    if (!executed)
                    {
                        ExecuteFunction(parameters);
                    }
                    return(new EmptyCommandResult());

                case CommandResultType.String:
                    if (!executed)
                    {
                        result   = ExecuteFunction(parameters);
                        executed = true;
                    }
                    if (!string.IsNullOrEmpty(result?.ToString()))
                    {
                        return(new StringCommandResult(result.ToString()));
                    }
                    break;

                case CommandResultType.Json:
                    if (!executed)
                    {
                        result   = ExecuteFunction(parameters);
                        executed = true;
                    }
                    if (result is JsonObject jsonResult)
                    {
                        return(new JsonCommandResult(jsonResult));
                    }
                    break;
                }
            }
            // Try to return an empty string
            if (returnTypes.Contains(CommandResultType.String) && executed)
            {
                return(new StringCommandResult(""));
            }
            throw new CommandException("Couldn't find a proper command result for function " + internCommand.Name, CommandExceptionReason.NoReturnMatch);
        }
Exemplo n.º 3
0
        public virtual object Execute(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <Type> returnTypes)
        {
            // Make arguments lazy, we only want to execute them once
            arguments = arguments.Select(c => new LazyCommand(c)).ToArray();
            var parameters = FitArguments(info, arguments, returnTypes, out int availableArguments);

            // Check if we were able to set enough arguments
            int wantArgumentCount = Math.Min(parameters.Length, RequiredParameters);

            if (availableArguments < wantArgumentCount)
            {
                if (returnTypes.Contains(typeof(ICommand)))
                {
                    return(arguments.Count > 0
                                                ? (object)new AppliedCommand(this, arguments)
                                                : this);
                }
                throw ThrowAtLeastNArguments(wantArgumentCount);
            }

            if (returnTypes[0] == null)
            {
                // Evaluate
                ExecuteFunction(parameters);
                return(null);
            }

            if (returnTypes[0] == typeof(ICommand))
            {
                // Return a command if we can take more arguments
                if (CommandParameter.Any(p => p.Type == typeof(string[])) || availableArguments < NormalParameters)
                {
                    return(new AppliedCommand(this, arguments));
                }
            }

            Log.Debug("Iterating over return types [{@returnTypes}]", returnTypes);

            var result = ExecuteFunction(parameters);

            if (ResultHelper.IsValidResult(result, returnTypes))
            {
                Log.Debug("{0} can be directly returned", result);
                return(result);
            }

            if (result == null)
            {
                throw new CommandException("Couldn't find a proper command result for function " + internCommand.Name, CommandExceptionReason.NoReturnMatch);
            }
            var unwrapedResult     = UnwrapReturn(result);
            var resultType         = result.GetType();
            var unwrapedResultType = unwrapedResult.GetType();

            // Take first fitting command result
            foreach (var returnType in returnTypes)
            {
                if (returnType == null)
                {
                    return(null);
                }

                if (returnType.IsAssignableFrom(resultType))
                {
                    return(ResultHelper.ToResult(returnType, result));
                }
                else if (returnType.IsAssignableFrom(unwrapedResultType))
                {
                    return(ResultHelper.ToResult(returnType, unwrapedResult));
                }
                else if (returnType == typeof(string))
                {
                    Log.Debug("Convert result to a string");
                    var resultStr = result.ToString();
                    if (!string.IsNullOrEmpty(resultStr))
                    {
                        return(new PrimitiveResult <string>(resultStr));
                    }
                }
                else if (BasicTypes.Contains(returnType))
                {
                    if (BasicTypes.Contains(unwrapedResultType) && unwrapedResultType != typeof(string))
                    {
                        // Automatically try to convert between primitive types
                        try
                        {
                            return(ResultHelper.ToResult(resultType,
                                                         Convert.ChangeType(unwrapedResult, returnType, CultureInfo.InvariantCulture)));
                        }
                        catch
                        {
                        }
                    }
                }
                else if (returnType == typeof(JsonObject))
                {
                    if (result is JsonObject jsonResult)
                    {
                        return(jsonResult);
                    }
                    else
                    {
                        return(Activator.CreateInstance(typeof(JsonValue <>).MakeGenericType(result.GetType()), result));
                    }
                }
                // Ignore unknown types
            }
            throw new CommandException("Couldn't find a proper command result for function " + internCommand.Name, CommandExceptionReason.NoReturnMatch);
        }