Esempio n. 1
0
        // The `Type` must override `ToString` so the builder can actually build the command.
        public Command WithArgument(string name, Type type, bool trailing = false)
        {
            if (HasSubCommands)
            {
                throw new InvalidOperationException("A command cannot have both arguments and sub-commands");
            }
            if (OrderedArgumentDefinitions == null)
            {
                OrderedArgumentDefinitions = new OrderedDictionary/*<string, ArgumentDefinition>*/ ();
            }
            if (_HasTrailingArg)
            {
                throw new InvalidOperationException("A command cannot have any arguments after a trailing argument");
            }

            if (trailing)
            {
                _HasTrailingArg = true;
            }

            //// Construct a `ArgumentDefinition<T>` using the passed `type` as `T`.
            //Type genericArgumentDefinitionType = typeof(ArgumentDefinition<>).MakeGenericType(type);
            //object argDef = Activator.CreateInstance(genericArgumentDefinitionType, name, trailing);

            ArgumentDefinition definition = new ArgumentDefinition(type, name, trailing);

            OrderedArgumentDefinitions.Add(name, definition);
            NumArguments++;
            return(this);
        }
Esempio n. 2
0
        public BoundCommand BindArgument <T>(string argName, T argValue)
        {
            if (!HasArguments)
            {
                string message = string.Format("Command {0} does not accept any arguments", Command.Name);
                throw new InvalidOperationException(message);
            }
            if (!Command.AcceptsArgument(argName))
            {
                string message = string.Format("Command {0} does not accept argument {1}", Command.Name, argName);
                throw new InvalidOperationException(message);
            }

            Type argValueType = typeof(T);
            ArgumentDefinition argDefinition = (ArgumentDefinition)Command.OrderedArgumentDefinitions[argName];

            if (!argValueType.IsSameOrSubclass(argDefinition.Type))
            {
                string message = string.Format("Command {0} accepts argument {1} with type {2}, but received type {3}",
                                               Command.Name, argName, argDefinition.Type.Name, typeof(T).Name);
                throw new InvalidOperationException(message);
            }

            ArgumentValues.Add(argName, argValue);
            IsDirty = true;
            return(this);
        }
Esempio n. 3
0
        public BoundCommand BindArguments(object[] argValues)
        {
            int numProvidedArgs = argValues != null ? argValues.Length : 0;
            int numRequiredArgs = Command.NumArguments;

            if (numProvidedArgs != numRequiredArgs)
            {
                throw new InvalidOperationException(string.Format(
                                                        "Command {0} requires {1} arguments, but only {2} were provided",
                                                        Command.Name, numRequiredArgs, numProvidedArgs));
            }

            int i = 0;

            foreach (DictionaryEntry entry in Command.OrderedArgumentDefinitions)
            {
                ArgumentDefinition acceptedArgDefinition = (ArgumentDefinition)entry.Value;
                string             acceptedArgName       = (string)entry.Key;
                Type acceptedArgType = acceptedArgDefinition.Type;
                // The call below DOES NOT CORRECTLY validate argument types.
                BindArgument(acceptedArgName, argValues[i++]);
            }

            return(this);
        }
Esempio n. 4
0
        private static BoundCommand ParseMessage(Message msg, out string errorMessage, Command[] acceptedCommands, BoundCommand lastCommand = null)
        {
            string currentToken = msg.NextToken();

            if (currentToken == null)
            {
                errorMessage = lastCommand == null ? "Invalid command" : null;
                return(lastCommand);
            }

            Command commandMatch = Array.Find(acceptedCommands, delegate(Command cmd)
            {
                return(currentToken.Equals(cmd.Name, StringComparison.InvariantCulture));
            });

            if (commandMatch == null)
            {
                errorMessage = string.Format("Unknown command: {0}", currentToken);
                return(null);
            }

            BoundCommand boundCommand = new BoundCommand(commandMatch);

            if (commandMatch.HasSubCommands)
            {
                // Find sub-command.
                boundCommand = ParseMessage(msg, out errorMessage, commandMatch.SubCommands.ToArray(), boundCommand);
            }
            else if (commandMatch.HasArguments)
            {
                LinkedList <string> argValues = new LinkedList <string>();

                // Read and validate arguments.
                foreach (DictionaryEntry entry in commandMatch.OrderedArgumentDefinitions)
                {
                    ArgumentDefinition definedArg     = (ArgumentDefinition)entry.Value;
                    string             definedArgName = (string)entry.Key;
                    Type   definedArgType             = definedArg.Type;
                    string passedArgValue             = definedArg.Trailing ? msg.RemainingTokens() : msg.NextToken();

                    try
                    {
                        bool isString = definedArgType.IsSameOrSubclass(typeof(string));
                        if (isString)
                        {
                            boundCommand.BindArgument(definedArgName, passedArgValue);
                        }
                        else
                        {
                            bool isComplex = definedArgType.IsSameOrSubclass(typeof(ComplexArgument));
                            if (isComplex)
                            {
                                dynamic deserializedValue = JsonConvert.DeserializeObject(passedArgValue, definedArgType);
                                boundCommand.BindArgument(definedArgName, deserializedValue);
                            }
                            else
                            {
                                dynamic convertedArgValue = Convert.ChangeType(passedArgValue, definedArgType);
                                boundCommand.BindArgument(definedArgName, convertedArgValue);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        errorMessage = ex.Message;
                        return(null);
                    }

                    if (definedArg.Trailing)
                    {
                        break;                         // There shouldn't be any arguments after this one.
                    }
                }
            }

            errorMessage = null;
            return(boundCommand);
        }
Esempio n. 5
0
        protected void Build()
        {
            Stack <Command> commandStack = new Stack <Command>();

            // Stack commands until there is no parent.
            // For example: 1 RUN PLAN CONTROL
            for (Command cmd = this.Command; cmd != null; cmd = cmd.Parent)
            {
                commandStack.Push(cmd);
            }

            int numCommands = commandStack.Count;

            if (numCommands == 0)
            {
                BuiltCommand = null;
                IsDirty      = false;
                return;
            }

            // Then unstack them and add to a list.
            // For example: CONTROL PLAN RUN 1
            List <string> commandList = new List <string>(numCommands);

            for (int i = 0; i < numCommands; i++)
            {
                Command cmd = commandStack.Pop();
                commandList.Add(cmd.Name);

                if (cmd.HasArguments)
                {
                    foreach (DictionaryEntry acceptedArg in cmd.OrderedArgumentDefinitions)
                    {
                        ArgumentDefinition acceptedArgDefinition = (ArgumentDefinition)acceptedArg.Value;
                        string             acceptedArgName       = (string)acceptedArg.Key;
                        Type acceptedArgType = acceptedArgDefinition.Type;

                        bool found = ArgumentValues.ContainsKey(acceptedArgName);
                        if (!found)
                        {
                            throw new InvalidOperationException(string.Format(
                                                                    "Command {0} requires argument {1}", cmd.Name, acceptedArgName));
                        }

                        object passedArgValue = ArgumentValues[acceptedArgName];
                        Type   passedArgType  = passedArgValue.GetType();
                        if (!passedArgType.IsSameOrSubclass(acceptedArgType))
                        {
                            throw new InvalidOperationException(string.Format(
                                                                    "Command {0} requires argument {1} of type {2}",
                                                                    cmd.Name, acceptedArgName, acceptedArgType.ToString()));
                        }

                        bool isComplex = passedArgType.IsSameOrSubclass(typeof(ComplexArgument));
                        if (isComplex)
                        {
                            string serializedValue = NotNullJsonSerializer.SerializeObject(passedArgValue);                             // Needs strong typing?
                            commandList.Add(serializedValue);
                        }
                        else
                        {
                            commandList.Add(passedArgValue.ToString());
                        }
                    }

                    break;                     // Ignore remaining commands.
                }
            }

            // Then transform it into a valid command string.
            BuiltCommand = string.Join(" ", commandList);
            IsDirty      = false;
        }