static void Run() { while (true) { var consoleInput = ReadFromConsole(); if (string.IsNullOrWhiteSpace(consoleInput)) continue; try { var command = new ConsoleCommand(consoleInput); string result = Execute(command); WriteToConsole(result); } catch (Exception ex) { WriteToConsole(ex.Message); } } }
static string Execute(ConsoleCommand command) { string invalidOperation = "Command does not exist"; //check command exists if (!_commandLibraries.ContainsKey(command.LibraryClassName)) { return invalidOperation; } var methodDictionary = _commandLibraries[command.LibraryClassName]; if (!methodDictionary.ContainsKey(command.Name)) { return invalidOperation; } //Validate paramters are correct var methodParameterValueList = new List<object>(); IEnumerable<ParameterInfo> paramInfoList = methodDictionary[command.Name].ToList(); var requiredParams = paramInfoList.Where(p => p.IsOptional == false); var optionalParams = paramInfoList.Where(p => p.IsOptional == true); int requiredCount = requiredParams.Count(); int optionalCount = optionalParams.Count(); int providedCount = command.Arguments.Count(); if (requiredCount > providedCount) { return string.Format( "Missing required arguments. {0} required, {1} optional, {2} provided", requiredCount, optionalCount, providedCount); } //TODO get required parameter names/info if (paramInfoList.Count() > 0) { //returns null if the parameter is required. TODO modify this to a dictionary of parameter names and values foreach (var param in paramInfoList) { methodParameterValueList.Add(param.DefaultValue); } } //parse provided parameters///////////////////////////////////////////////////// for (int i = 0; i < command.Arguments.Count(); i++) { var methodParam = paramInfoList.ElementAt(i); var typeRequired = methodParam.ParameterType; object value = null; try { value = CoerceArgument(typeRequired, command.Arguments.ElementAt(i)); methodParameterValueList.RemoveAt(i); methodParameterValueList.Insert(i, value); } catch (ArgumentException) { string argumentName = methodParam.Name; string argumentTypeName = typeRequired.Name; string message = string.Format( "The value passes for argument '{0}' cannot be parsed to type '{1}'", argumentName, argumentTypeName); throw new ArgumentException(message); } ////////////////////////////////////////////////////////////////////////////// } //invoke the method using reflection Assembly currentAssembly = typeof(Program).GetTypeInfo().Assembly; Type commandLibraryClass = currentAssembly.GetType(_commandNamespace + "." + command.LibraryClassName); object[] inputArgs = null; if (methodParameterValueList.Count > 0) { inputArgs = methodParameterValueList.ToArray(); } var typeInfo = commandLibraryClass; try { var method = typeInfo.GetTypeInfo().GetMethod(command.Name, BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public); var result = method.Invoke(null, inputArgs); return result.ToString(); } catch (TargetInvocationException ex) { throw ex.InnerException; } }