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); }
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); }
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); }