I applied the CQRS approach in my application, very dependent on this fantastic article: https://cuttingedge.it/blogs/steven/pivot/entry.php?id=9 . My code for commands and handlers is identical to the article, and this part works well. My problem arises when I try to implement a decorator class to check command validation. Simple command processing interfaces are as follows:
public interface ICommand { } public interface ICommandHandler<TCommand> { void Handle(TCommand command); }
Then for the check decorator there are:
public class ValidationCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand> where TCommand : CommandBase { private readonly ICommandHandler<TCommand> _decoratedCommandHandler; private readonly ICommandValidator<TCommand> _commandValidator; public ValidationCommandHandlerDecorator(ICommandHandler<TCommand> decoratedCommandHandler, ICommandValidator<TCommand> commandValidator) { _decoratedCommandHandler = decoratedCommandHandler; _commandValidator = commandValidator; } public void Handle(TCommand command) { if (_commandValidator != null) { var validationResult = _commandValidator.Validate(command); if (validationResult != null) { command.Success = false; command.Errors = validationResult; return; } } _decoratedCommandHandler.Handle(command); command.Success = true; } }
Uses an interface to define validators:
public interface ICommandValidator<TCommand> { IEnumerable<string> Validate(TCommand command); }
And CommandBase is a simple base class that allows me to save the success or failure of a command and the errors that occurred if it failed. I prefer this method as an alternative to throwing an exception. All teams inherit this base class.
public abstract class CommandBase : ICommand { public bool Success { get; set; } public IEnumerable<string> Errors { get; set; } }
And all this is connected to the IoC container in the structural map registry:
public class CommandRegistry : Registry { public CommandRegistry() { Scan(s => { s.AssemblyContainingType<CommandBase>(); s.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>)); s.ConnectImplementationsToTypesClosing(typeof(ICommandValidator<>)); s.WithDefaultConventions(); For(typeof(ICommandHandler<>)).DecorateAllWith(typeof(ValidationCommandHandlerDecorator<>)); }); } }
Now, since I register this decorator for each individual ICommandHandler, if I ever have a command that does not need a validator and does not define it, the private field ICommandValidator<TCommand> _commandValidator of the ValidationCommandHandlerDecorator<TCommand> class cannot be found because it , of course, does not exist and will always cause a structural map error:
"No instance is registered by default and cannot be automatically detected for type" ICommandValidator. "No configuration specified for ICommandValidator."
Is there a way in the map structure to determine how to build a ValidationCommandHandlerDecorator so that it uses some type of check by default when it does not exist, without having to either take a dependency on the container in the class, or create an IValidateableCommandHandler<TCommand> interface to process commands using validators?
Thanks.