private void RegisterControllerInternal(Type controllerType, CommandControllerBase controller) { if (_registeredControllerTypes.Contains(controllerType)) { throw new ArgumentException("A controller of the same type has already been registered.", nameof(controllerType)); } if (_dependencyResolver == null && !controllerType.GetConstructors().Any(c => c.GetParameters().Length == 0)) { throw new ArgumentException("The type of controller does not have a parameterless constructor and no dependency controller is used for this service.", nameof(controllerType)); } string prefix = string.Empty; bool controllerCaseSensitive = false; bool instantiatePerCommand = false; CommandControllerAttribute controllerAttribute = controllerType.GetCustomAttributes(typeof(CommandControllerAttribute), true).FirstOrDefault() as CommandControllerAttribute; if (controllerAttribute != null) { prefix = controllerAttribute.Prefix; controllerCaseSensitive = controllerAttribute.CaseSensitiveRouting; instantiatePerCommand = controller == null ? controllerAttribute.InstantiatePerExecutedCommand : false; } const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public; foreach (MethodInfo method in controllerType.GetMethods(flags)) { foreach (CommandAttribute attribute in method.GetCustomAttributes(typeof(CommandAttribute), true)) { string fullRoute = attribute.UseControllerPrefix ? prefix + attribute.Route : attribute.Route; CommandData commandData = new CommandData { Arguments = method.GetParameters() .Select(p => new CommandArgument { Name = p.Name, Type = p.ParameterType }) .ToList(), CaseSensitive = attribute.IsCaseSensitiveRoutingSet ? attribute.CaseSensitiveRouting : controllerCaseSensitive, InstantiatePerExecutedCommand = instantiatePerCommand, ControllerType = controllerType, ControllerInstance = controller, Method = method, RouteParts = CommandRouteParser.GetRouteParts(fullRoute), Description = attribute.Description }; _commandDataCollection.Add(commandData); } } _registeredControllerTypes.Add(controllerType); }
/// <summary> /// Maps the methods of the given <see cref="CommandControllerBase" /> instance to their respective methods, using the <see cref="CommandAttribute" /> attribute. /// Ignores the <see cref="CommandControllerAttribute.InstantiatePerExecutedCommand" /> setting and reuses the given <see cref="CommandControllerBase" /> instance for each command. /// </summary> /// <param name="controller">The <see cref="CommandControllerBase" /> containing the methods to register.</param> /// <exception cref="ArgumentNullException"><paramref name="controller"/> is <c>null</c>.</exception> public void RegisterControllerConstant(CommandControllerBase controller) { if (controller == null) { throw new ArgumentNullException(nameof(controller), "'controller' cannot be null."); } lock (_syncRoot) { RegisterControllerInternal(controller.GetType(), controller); } }
private CommandControllerBase InstantiateController(Type controllerType) { if (_dependencyResolver == null) { return((CommandControllerBase)Activator.CreateInstance(controllerType)); } object instanceObj = _dependencyResolver.GetService(controllerType); if (instanceObj == null) { throw new ArgumentException($"Unable to resolve a controller of type '{controllerType}'.", nameof(controllerType)); } CommandControllerBase instance = instanceObj as CommandControllerBase; if (instance == null) { throw new ArgumentException($"The resolved controller of type '{controllerType}' does not implement the .", nameof(controllerType)); } return(instance); }
internal CommandServiceEventArgs(CommandService service, CommandControllerBase controller) { Service = service; Controller = controller; }
internal void FireExitEvent(CommandControllerBase controller) { EventHandler <CommandServiceEventArgs> exitEventHandler = Exit; exitEventHandler?.Invoke(this, new CommandServiceEventArgs(this, controller)); }
/// <summary> /// Executes the specified command line. /// </summary> /// <param name="commandLine">The command line.</param> /// <returns>Result information as a <see cref="CommandResult"/> object.</returns> /// <exception cref="CommandException">A detailed exception wrapper, thrown when execution goes wrong.</exception> public CommandResult Execute(string commandLine) { if (string.IsNullOrEmpty(commandLine)) { throw new CommandException("No command line specified.", commandLine, CommandErrorCode.EmptyInput, null); } lock (_syncRoot) { foreach (CommandData commandData in _commandDataCollection) { Dictionary <string, string> argumentValues; if (CommandRouteParser.TryParseCommandLine(commandLine, commandData.RouteParts, commandData.CaseSensitive, out argumentValues)) { int argumentCount = commandData.Arguments.Count; object[] parsedArguments = new object[argumentCount]; for (int i = 0; i < argumentCount; i++) { CommandArgument argumentData = commandData.Arguments[i]; string argumentValue; ICommandArgumentParser argumentParser; if (!argumentValues.TryGetValue(argumentData.Name, out argumentValue)) { parsedArguments[i] = argumentData.Type.IsValueType ? Activator.CreateInstance(argumentData.Type) : null; } else if (_argumentParsers.TryGetValue(argumentData.Type, out argumentParser)) { try { parsedArguments[i] = argumentParser.Parse(argumentData.Name, argumentValue); } catch (Exception ex) { throw new CommandException(commandLine, "An argument parser threw an exception.", CommandErrorCode.ArgumentParseError, ex); } } else if (typeof(IConvertible).IsAssignableFrom(argumentData.Type)) { try { parsedArguments[i] = Convert.ChangeType(argumentValue, argumentData.Type); } catch (Exception ex) { throw new CommandException(commandLine, "There was an error converting an argument.", CommandErrorCode.ArgumentParseError, ex); } } else { throw new CommandException(commandLine, $"Could not find a way to parse argument '{argumentData.Name}'.", CommandErrorCode.ArgumentParseError, null); } } CommandControllerBase controller = null; if (commandData.InstantiatePerExecutedCommand) { controller = InstantiateController(commandData.ControllerType); } else if (commandData.ControllerInstance == null) { commandData.ControllerInstance = controller = InstantiateController(commandData.ControllerType); } else { controller = commandData.ControllerInstance; } controller.CommandServiceInternal = this; controller.CommandLineInternal = commandLine; controller.LastResultInternal = _lastResult; try { _lastResult = commandData.Method.Invoke(controller, parsedArguments); } catch (Exception ex) { throw new CommandException("An error occured while executing the command method.", commandLine, CommandErrorCode.CommandError, ex); } return(new CommandResult(_lastResult, controller.GetType(), commandData.Method)); } } throw new CommandException("No route matched the input.", commandLine, CommandErrorCode.UnknownCommand, null); } }