-
-
Save rhyss/2318508 to your computer and use it in GitHub Desktop.
Validation within Aggregate Roots - Part 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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