/// <summary> /// Execute a validated command by sending the message to an aggregate. If the command is valid, the command will be processed /// by the aggregate. When the command has been handled successfully, and events are returned as a result, the events /// are aggregated to create the next state of the viewmodel, by calling the user defined Update function. /// Then a notification is sent to signal the state of the viewmodel has changed. This will trigger the component /// to rerender, so that it can show the correct state in the user interface. This rerendering triggers the user defined View /// function, which signifies how the view should be rendered /// </summary> /// <param name="target">The aggrgate that will handle the command</param> /// <param name="command">The validate command that the aggregate will handle, if it is valid. </param> /// <returns>When the command is not valid, it will return Some errors, None otherwise</returns> protected async Task <Option <Error[]> > Dispatch(Aggregate <TCommand, TEvent> target, Validated <TCommand> command) { Result <CommandResult <TEvent>, Error[]> result = await target.Accept(command); switch (result) { case Ok <CommandResult <TEvent>, Error[]>(var commandResult): _shouldRender = commandResult.Events.Any(); ViewModel = Update(ViewModel, commandResult.Events); StateHasChanged(); return(None <Error[]>()); case Error <CommandResult <TEvent>, Error[]>(var errors): _shouldRender = true; ViewModel.Errors = errors; StateHasChanged(); return(Some(errors)); default: _shouldRender = false; throw new ArgumentOutOfRangeException(nameof(result)); } }