Skip to content

Instantly share code, notes, and snippets.

@rhyss
Forked from PaulUpson/CommandValidator.cs
Created April 6, 2012 09:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rhyss/2318508 to your computer and use it in GitHub Desktop.
Save rhyss/2318508 to your computer and use it in GitHub Desktop.
Validation within Aggregate Roots - Part 2
public interface IValidationHandler<in T> where T : Command {
bool Validate(T cmd);
}
public interface ICommandValidator {
bool Validate<T>(T command) where T : Command;
}
// Allows for all command validators to be registered on app start
public class CommandValidator : ICommandValidator {
private readonly IDictionary<Type, Func<object, bool>> _validationHandlers = new Dictionary<Type, Func<object, bool>>();
public void RegisterValidator<T>(Func<T,bool> handler) where T : Command {
_validationHandlers.Add(typeof(T), o => handler((T) o));
}
public bool Validate<T>(T command) where T : Command {
Func<object, bool> handler;
return !_validationHandlers.TryGetValue(command.GetType(), out handler) || handler(command);
}
}
// Class to encapsulate all command validation rules for an Aggregate Root
public class PatientValidationHandler : IValidationHandler<AddReferredPatient>, IValidationHandler<ChangePatientAddress> {
public bool Validate(AddReferredPatient command) {
if (string.IsNullOrWhitespace(command.Firstname))
throw new CommandValidationException("firstname", "First Name is required");
}
// Register your command validators as you might your command handlers (N.B. this could be done with an IoC or reflection to auto-wireup)
var patientValidator = new PatientValidationHandler();
validator.RegisterValidator<AddReferredPatient>(patientValidator.Validate);
validator.RegisterValidator<ChangePatientAddress>(patientValidator.Validate);
// Then on all command sending
protected void Send<T>(T cmd) where T : Command {
try {
if (Validator.Validate(cmd)) {
Bus.Send(cmd);
}
}
catch (ValidationException ex) {
// This catches both Command Validation exception and Domain validation exceptions (which both inherit from ValidationException)
// manage your feedback to the UI as you see fit but I've gone with the below.
foreach(var error in ex.Errors) {
ModelState.AddModelError(error.ParamName, error.Message);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment