Skip to content

CQS 4.0

Latest
Compare
Choose a tag to compare
@meinsiedler meinsiedler released this 22 Aug 09:16
· 7 commits to master since this release
c144858

Breaking Changes

  • There is now an interface ICommand<TResult> for commands that return values. While this should be used sparingly, there are some cases where it can be useful.
  • ICommand (which should be the default for implementing commands) derives from this new ICommand<NoResult> interface.
  • There is now a common base interface for IQuery<TResult> and ICommand<TResult> (and thus ICommand): IRequest<TResult. This has the following advantages:
    • There is no need to distinguish between IQueryHandler<TResult> and ICommandHandler anymore. Simply use IRequestHandler<TResult>.
    • For cross-cutting concerns, you can write decorators that target IRequestHandler<TResult>. Before you had to write one for IQueryHandler<TResult> and one for ICommandHandler.
    • Instead of IQueryProcessor and ICommandProcessor, you can simply use IRequestProcessor. ExecuteAsync has been renamed to HandleAsync.
  • The cancellation token is now a required parameter for the HandleAsync method.
Show detailed upgrade instructions
  • Update all softaware.CQS packages to version 4.0.0 or higher

  • Replace IQueryHandler<TQuery, TResult> with IRequestHandler<TQuery, TResult>:

    • Replace in files (Use regular expression)
      IQueryHandler<(.*?), (.*?)>
      IRequestHandler<$1, $2>
  • Replace ICommandHandler<TCommand> with IRequestHandler<TCommand, NoResult>

    • Replace
      ICommandHandler<(.*?)>
      IRequestHandler<$1, NoResult>
  • Replace query handler HandleAsync interface implementation: Add CancellationToken

    • Replace
      Task<(.+?)> HandleAsync\(([^,]+?) ([^,]+?)\)
      Task<$1> HandleAsync($2 $3, System.Threading.CancellationToken cancellationToken)
  • Replace command handler HandleAsync: add NoResult and CancellationToken

    • Replace
      Task HandleAsync\(([^,]+?) ([^,]+?)\)
      Task<NoResult> HandleAsync($1 $2, System.Threading.CancellationToken cancellationToken)
  • Remove HandleAsync overloads delegating to CancellationToken version

    • Replace with empty string (You might need to adjust the expressions based on your formatting):
      Task<(.+?)> HandleAsync\(([^,]+?) ([^,]+?)\) =>
    • Replace with empty string
      public  this.HandleAsync(query, default);
  • Replace IQueryProcessor and ICommandProcessor with IRequestProcessor

    • Replace IQueryProcessor with IRequestProcessor
    • Replace ICommandProcessor with IRequestProcessor
    • Replace queryProcessor with requestProcessor
    • Replace commandProcessor with requestProcessor
    • Replace
      requestProcessor.ExecuteAsync\(([^,]+?)\);
      requestProcessor.HandleAsync($1, cancellationToken);
    • Remove duplicates where IQueryProcessor and ICommandProcessor were injected
  • Add return NoResult.Value to command handlers

  • Optional: Add CancellationToken to Controller actions

    • Replace with file pattern: *Controller.cs

    • With parameters:

      public async (.+)\((.+)\)
      public async $1($2, System.Threading.CancellationToken cancellationToken)
      • Without parameters:
      public async (.+)\(\)
      public async $1(System.Threading.CancellationToken cancellationToken)
  • Add missing CancellationToken parameters

  • Decorators: Refactor command handler decorators to 2 generic type parameters

  • Replace AddQueryHandlerDecorator and AddCommandHandlerDecorator with AddRequestHandlerDecorator

  • Remove PublicQueryHandlerDecorator and PublicCommandHandlerDecorator if you referenced them explicitely.

  • Optional: Combine duplicate decorators implementing IQueryHandler<TResult> and ICommandHandler into a single class implementing IRequestHandler

  • Optional: Use ICommand<TResult> instead of ICommand if you used some workarounds for returning values from commands (like setting a property on the command)