Which one of us doesn’t like to give commands? It’s the natural way to ask (in a polite way) for a specific task that needs to be completed. Therefore, it shouldn’t be surprising that the command pattern can be also easily implemented within our software, which might provide some serious benefits in terms of loose coupling the existing code.





This is going to be mostly about the code, so let’s write some code and find out what’s the fuss about:

//Marker public interface ICommand { } public interface ICommandHandler<in T> where T : ICommand { Task HandleAsync(T command); } public interface ICommandDispatcher { Task DispatchAsync<T>(T command) where T : ICommand; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //Marker public interface ICommand { } public interface ICommandHandler < in T > where T : ICommand { Task HandleAsync ( T command ) ; } public interface ICommandDispatcher { Task DispatchAsync < T > ( T command ) where T : ICommand ; }

At first, let’s define three simple interfaces. The first one is merely a marker interface, and the second one is actually responsible for ensuring that the given command goes into the right direction. The last fella is a kind of helper, that dispatches the commands automatically (to the appropriate instance of the ICommandHandler). Let’s stay with him for a while and see how we could implement such functionality e.g. by using the IoC container (Autofac in this example):

public class CommandDispatcher : ICommandDispatcher { private readonly IComponentContext _context; public CommandDispatcher(IComponentContext context) { _context = context; } public async Task DispatchAsync<T>(T command) where T : ICommand { if (command == null) { throw new ArgumentNullException(nameof(command), "Command can not be null."); } var handler = _context.Resolve<ICommandHandler<T>>(); await handler.HandleAsync(command); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class CommandDispatcher : ICommandDispatcher { private readonly IComponentContext _context ; public CommandDispatcher ( IComponentContext context ) { _context = context ; } public async Task DispatchAsync < T > ( T command ) where T : ICommand { if ( command == null ) { throw new ArgumentNullException ( nameof ( command ) , "Command can not be null." ) ; } var handler = _context . Resolve < ICommandHandler < T >> ( ) ; await handler . HandleAsync ( command ) ; } }

Ok, so what’s actually the command entity? Just a class, that may contain some properties:

public class CreateUser : ICommand { public Guid UserId { get; set; } public string Email { get; set; } public string Password { get; set; } public string Nickname { get; set; } public string Culture { get; set; } } 1 2 3 4 5 6 7 8 public class CreateUser : ICommand { public Guid UserId { get ; set ; } public string Email { get ; set ; } public string Password { get ; set ; } public string Nickname { get ; set ; } public string Culture { get ; set ; } }

And the handler for such command:

public class CreateUserHandler : ICommandHandler<CreateUser> { private readonly IUserService _userService; public CreateUserHandler(IUserService userService) { _userService = userService; } public async Task HandleAsync(CreateUser command) { await _userService.RegisterAsync(command.UserId, command.Email, command.Password, command.Nickname, command.Culture); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class CreateUserHandler : ICommandHandler < CreateUser > { private readonly IUserService _userService ; public CreateUserHandler ( IUserService userService ) { _userService = userService ; } public async Task HandleAsync ( CreateUser command ) { await _userService . RegisterAsync ( command . UserId , command . Email , command . Password , command . Nickname , command . Culture ) ; } }

And what’s the benefit? Well, most importantly the commands encapsulate the business logic. They might also be a part of a bigger flow – events and some other useful stuff that I’ll talk about in the future. Please take a look, how we can make use of the ICommandDispatcher within the MVC application:

public class UserController : Controller { private readonly ICommandDispatcher _dispatcher; public UserController(ICommandDispatcher dispatcher) { _dispatcher = dispatcher; } [HttpPost] public async Task<ActionResult> Create(CreateUser command) { await _dispatcher.DispatchAsync(command); //Set the Location header, to be a really cool, RESTful guy. return new HttpStatusCodeResult(HttpStatusCode.Created); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class UserController : Controller { private readonly ICommandDispatcher _dispatcher ; public UserController ( ICommandDispatcher dispatcher ) { _dispatcher = dispatcher ; } [ HttpPost ] public async Task < ActionResult > Create ( CreateUser command ) { await _dispatcher . DispatchAsync ( command ) ; //Set the Location header, to be a really cool, RESTful guy. return new HttpStatusCodeResult ( HttpStatusCode . Created ) ; } }

Again, a rather simplistic example. You might want to pass the view model first, then map it into the command etc. The key here is to realize the benefit of using the commands and abstracting away all the business logic e.g. from the controllers. The commands also fit nicely within the CQS and CQRS patterns, which are very powerful.

In one of the next posts, I’ll show you how to make your actions inside the Web/API controllers look cool (at least for me) while using the commands. And that’s a little sneak peek:

public async Task<ActionResult> EditPassword(PasswordViewModel viewModel) => await For(viewModel.MapTo<EditUserPassword>()) .ExecuteAsync(c => Dispatcher.DispatchAsync(c)) .OnSuccessNotify(Resources.PasswordHasBeenChanged) .OnFailureNotify(ex => ex.Message) .OnComplete(c => RedirectToRoute(Routes.UserDetails, new {id = viewModel.Id})) .HandleAsync(); 1 2 3 4 5 6 7 public async Task < ActionResult > EditPassword ( PasswordViewModel viewModel ) = > await For ( viewModel . MapTo < EditUserPassword > ( ) ) . ExecuteAsync ( c = > Dispatcher . DispatchAsync ( c ) ) . OnSuccessNotify ( Resources . PasswordHasBeenChanged ) . OnFailureNotify ( ex = > ex . Message ) . OnComplete ( c = > RedirectToRoute ( Routes . UserDetails , new { id = viewModel . Id } ) ) . HandleAsync ( ) ;