public void AddSubNode(List <string> words, MethodInvokeInfo methodInfo) { // We should never hit this case. if (words.Count == 0) { throw new InvalidOperationException("Out of words building command node."); } // Check the root to see if a node for the first incoming word has already been added DebuggerCommand subNode = FindSubNodeByName(words[0]); if (subNode == null) { // No, it has not -- create one and add it now. subNode = new DebuggerCommand(words[0], null, null, null); this.SubCommands.Add(subNode); if (words.Count == 1) { // This is the last stop -- set the method and be done with it now. subNode.Methods.Add(methodInfo); // early return. return; } } else { // The node already exists, we will be adding a subnode, hopefully. if (words.Count == 1) { // // If we're on the last word at this point then this is an overloaded command. // Check that we don't have any other commands with this number of arguments. // int argCount = methodInfo.Method.GetParameters().Length; foreach (MethodInvokeInfo info in subNode.Methods) { if (info.Method.GetParameters().Length == argCount) { throw new InvalidOperationException("Duplicate overload for console command"); } } // // We're ok. Add it to the method list. // subNode.Methods.Add(methodInfo); // and return early. return; } } // We have more words to go. words.RemoveAt(0); subNode.AddSubNode(words, methodInfo); }
public DebuggerCommand(string name, String description, String usage, MethodInvokeInfo methodInvoke) { Name = name.Trim().ToLower(); Description = description; Usage = usage; Methods = new List <MethodInvokeInfo>(4); if (methodInvoke != null) { Methods.Add(methodInvoke); } SubCommands = new List <DebuggerCommand>(); }
private CommandResult InvokeConsoleMethod(DebuggerCommand command, string[] args) { MethodInvokeInfo method = null; // // Find the method that matches the arg count we were passed // (i.e. handle overloaded commands). // That this only matches on argument count is somewhat of a kluge... // foreach (MethodInvokeInfo m in command.Methods) { ParameterInfo[] paramInfo = m.Method.GetParameters(); if (args == null && paramInfo.Length == 0 || paramInfo.Length == args.Length) { // found a match method = m; break; } } if (method == null) { // invalid argument count. throw new ArgumentException(String.Format("Invalid argument count to command.")); } ParameterInfo[] parameterInfo = method.Method.GetParameters(); object[] invokeParams; if (args == null) { invokeParams = null; } else { invokeParams = new object[parameterInfo.Length]; } int argIndex = 0; for (int paramIndex = 0; paramIndex < parameterInfo.Length; paramIndex++) { ParameterInfo p = parameterInfo[paramIndex]; if (p.ParameterType.IsEnum) { // // This is an enumeration type. // See if we can find an enumerant that matches the argument. // FieldInfo[] fields = p.ParameterType.GetFields(); foreach (FieldInfo f in fields) { if (!f.IsSpecialName && args[argIndex].ToLower() == f.Name.ToLower()) { invokeParams[paramIndex] = f.GetRawConstantValue(); break; } } if (invokeParams[paramIndex] == null) { // no match, provide possible values StringBuilder sb = new StringBuilder(String.Format("Invalid value for parameter {0}. Possible values are:", paramIndex)); foreach (FieldInfo f in fields) { if (!f.IsSpecialName) { sb.AppendFormat("{0} ", f.Name); } } sb.AppendLine(); throw new ArgumentException(sb.ToString()); } argIndex++; } else if (p.ParameterType.IsArray) { // // If a function takes an array type, i should do something here, yeah. // argIndex++; } else { if (p.ParameterType == typeof(bool)) { invokeParams[paramIndex] = bool.Parse(args[argIndex++]); } else if (p.ParameterType == typeof(uint)) { invokeParams[paramIndex] = TryParseUint(args[argIndex++]); } else if (p.ParameterType == typeof(ushort)) { invokeParams[paramIndex] = TryParseUshort(args[argIndex++]); } else if (p.ParameterType == typeof(string)) { invokeParams[paramIndex] = args[argIndex++]; } else if (p.ParameterType == typeof(char)) { invokeParams[paramIndex] = (char)args[argIndex++][0]; } else if (p.ParameterType == typeof(float)) { invokeParams[paramIndex] = float.Parse(args[argIndex++]); } else { throw new ArgumentException(String.Format("Unhandled type for parameter {0}, type {1}", paramIndex, p.ParameterType)); } } } // // If we've made it THIS far, then we were able to parse all the commands into what they should be. // Invoke the method on the object instance associated with the command. // return((CommandResult)method.Method.Invoke(method.Instance, invokeParams)); }