public async Task <ICommandResult> Execute(Command command) { if (command == null) { throw new ArgumentNullException(nameof(command)); } var iterator = new CommandIterator(command); var currentController = (CommandController <TContext>)Activator.CreateInstance(typeof(TMainController), _context, iterator); while (true) { ICommandResult result; if (iterator.HasNext) { result = await ExecuteControllerMethod(currentController, iterator, iterator.GetNext()).ConfigureAwait(false); } else { result = await ExecuteControllerMethod(currentController, iterator).ConfigureAwait(false); } if (result is ForwardResult forwardResult) { var args = new List <object>(); args.Add(_context); args.Add(iterator); args.AddRange(forwardResult.ControllerArgs); currentController = (CommandController <TContext>)Activator.CreateInstance(forwardResult.ControllerType, args.ToArray()); } else { return(result); } } throw new IncompleteCommandException("Command iterator reached end but execution chain goes on."); }
private Task <ICommandResult> ExecuteControllerMethod(CommandController <TContext> controller, CommandIterator commandIterator, string methodName = default) { MethodInfo method; if (methodName == default) { method = controller.GetType().GetMethods().FirstOrDefault(m => m.GetCustomAttribute <DefaultCommandAttribute>(true) != null); if (method == null) { throw new InvalidCommandException($"Controller {controller} has no default command handler."); } } else { method = controller.GetType().GetMethods().FirstOrDefault(m => m.GetCustomAttribute <CommandAttribute>(true)?.Command == methodName); if (method == null) { throw new InvalidCommandException($"Controller {controller} has no handler for the {methodName} command."); } } var args = new List <object>(); foreach (ParameterInfo parameter in method.GetParameters()) { if (!commandIterator.HasNext) { throw new IncompleteCommandException("Command iterator reached end but command method requires argument."); } args.Add(commandIterator.GetNext(parameter.ParameterType)); } return((Task <ICommandResult>)method.Invoke(controller, args.ToArray())); }
protected CommandController(TContext context, CommandIterator commandIterator) { Context = context ?? throw new ArgumentNullException(nameof(context)); CommandIterator = commandIterator ?? throw new ArgumentNullException(nameof(commandIterator)); }