Skip to content

Commands

João Simões edited this page Sep 7, 2017 · 10 revisions

To be able to change application state, this library has support for commands that are sent into a single and required command handler using generic variance.

Components

The following interfaces and abstract classes are used to implement the command pattern:

Interface/Class Description
ICommand interface that represents a command
ICommand<TResult> interface that represents a command that will have an operation result
Command abstract class that implements the ICommand interface
Command<TResult> abstract class that implements the ICommand<TResult> interface
ICommandHandler<TCommand> interface that will handle asynchronously a TCommand instance extending from ICommand
ICommandHandler<TCommand,TResult> interface that will handle asynchronously a TCommand instance extending from ICommand<TResult> and returning a given operation result
CommandHandlerNotFoundException exception thrown if no handler is found by the mediator when sending a command

Command properties

The following properties are included in the command interfaces:

Property Description
Id required unique identifier for each command. It may be used to detect command duplication or just for audit purposes. The abstract command classes will assign a Guid.NewGuid() value
CreatedOn required date and time in which the command was created. The abstract command classes will assign a DateTimeOffset.Now value
CreatedBy a string identifier for the user who created the command

Creating a command

To create a command just implement the ICommand or ICommand<TResult> interfaces or corresponding abstract classes:

public class CreateUserCommand<Guid> : Command<Guid>, ICommand<Guid> {
  public string Email { get; set; }
  public string Password { get; set; }
}

public class DeleteUserCommand : Command, ICommand {
  public Guid UserId { get; set; }
}

Handling a command

To handle a command just implement the ICommandHandler<TCommand> or ICommandHandler<TCommand,TResult> interfaces:

public class UserCommandHandler : ICommandHandler<CreateUserCommand,Guid>, ICommandHandler<DeleteUserCommand> {
  public async Task<Guid> HandleAsync(CreateUserCommand cmd, CancellationToken ct) {
    var userId = Guid.NewGuid();
    // try store the new user
    return userId;
  }

  public async Task HandleAsync(DeleteUserCommand cmd, CancellationToken ct) {
    // delete the user
  }
}

Sending a command

To send a command, you only need the mediator instance and use the SendAsync methods:

var userId = await _mediator.SendAsync<CreateUserCommand,Guid>(new CreateUserCommand {
  Email = "someone@domain.com",
  Password = "123456"
}, ct);
await _mediator.SendAsync<DeleteUserCommand>(new DeleteUserCommand {
  UserId = userId
}, ct);

Clone this wiki locally