The S#arp framework: adding validation to your objects

Today we’re going to keep looking at the S#arp framework and we’re going to take a look at how we can reuse the classes introduced by the framework to add validation to an object. Before going on, it’s important to keep in mind that validation is a topic which might generate lots of discussion.

For instance, there are lots of people which say that we should never let an object reach an invalid state (a position I’ve been liking a lot lately). Others say that it’s  perfectly OK to let an entity get into an invalid state…But even those that defend that position don’t agree regarding where that validation should take place (many say that the object should be responsible for validation while others say that validation should be performed by other objects). In my opinion, everything depends on the current context…

Having said  that, it’s time to  go back the S#arp framework and see how to add validation to our objects. In the present release, an object signals that it supports validation by implementing the IValidatable interface:

public interface IValidatable {
  bool IsValid();
  ICollection<IValidationResult> ValidationResults();

IValidationResult represents information about an error. Currently, this interface looks  like this:

public interface IValidationResult   {
  Type ClassContext { get; } 
  string PropertyName { get; } 
  string Message { get; }

ClassContext identifies the type associated to the current validation result. PropertyName identifies the name of the property that hasn’t a valid value and Message will always contain an error message to inform you about the problem. We still need to look at one last interface: the IValidator interface. It looks like this:

public interface IValidator {
  bool IsValid(object value);
  ICollection<IValidationResult> ValidationResultsFor(object value);

This interface should be implemented by any object that is responsible for performing validation, ie, it should be implemented by a validator. The current release of the platform relies on these three interfaces for supporting validation. Why such a “complicated” architecture? Well, it will all make sense when we look at the default implementation of these interfaces. However, do keep in mind that the only “real” requisite is that an object that signals its support to validation needs to implement the IValidationResult.

Having said this, lets go on and take a look at the ValidatableObject class. It expands the BaseObject class and implements the IValidatable interface:

public abstract class ValidatableObject : BaseObject,IValidatable {
       public virtual bool IsValid() {
           return Validator.IsValid(this);
       public virtual ICollection<IValidationResult> ValidationResults() {
           return Validator.ValidationResultsFor(this);
       private IValidator Validator {
           get {
               return SafeServiceLocator<IValidator>.GetService();

As you can see,the class uses the service locator pattern for getting a reference to the validation service (which implements the IValidator interface). The SafeServiceLocator performs its work by using the common service locator class but wraps its exceptions in new ones with more better error messages.

The default implementation of the IValidator interface relies on the ValidatorEngine introduced by the NH Validator framework. I’m not a user of this framework, so I’ll create my own implementation of IValidator interface to show you how you can reuse the ValidatableObject class with a custom implementation of a  validation engine.

[Before going, it’s important to notice that if you’re not using an IoC then you should probably bypass this class and implement the interface directly]

Let’s get started…we’ll change our last example in order to illustrate validation and we’re going to create a validator class for our SimpleAddress class. The first thing we need to do is to implement the IValidationResult interface to encapsulate error messages. The current implementation of this interface was built to encapsulate the error messages fired  by the NH Validator engine, so we  won’t be reusing this. We don’t need anything fancy, so this simple class will do it:

public class CustomError:IValidationResult {
  private static readonly Type _customType = typeof( SimpleAddress );
  private readonly String _propName;
  private readonly String _message; 
  public CustomError(String propName, String message) {
      _propName = propName;
      _message = message;
  public Type ClassContext {
            get { return _customType; }
  public string PropertyName {
            get { return _propName; }
  public string Message {
            get { return _message; }

Now that we have something to encapsulate return error info, we can proceed and implement the SimpleAddressValidator class:

public class SimpleAddressValidator:IValidator {
   public bool IsValid( object value ) {
            var address = value as SimpleAddress;
            if( address == null)
                throw new NotSupportedException();
            return ( String.IsNullOrEmpty( address.Street ) )
                           ? false
                           : true;
  public ICollection<IValidationResult> ValidationResultsFor( object value ) {
            var errors = new Collection<IValidationResult>();
            var address = value as SimpleAddress;
#160;   if( address == null ) {
                throw new NotSupportedException();
            if( String.IsNullOrEmpty( address.Street )) {
                errors.Add( new CustomError( "Street",
                                           "Street must have a valid value" ) );
            return errors;

The first thing we do is convert the value parameter into the expected type: when that operation fails, we simply throw a not supported exception. The only rule we have is that Address cannot be null!

Now, we can simply adapt the SimpleAddress class presented  earlier to reuse the ValidatableObject class:

public class SimpleAddress:ValidatableObject {
  public String Street { get; set; }
  public String ZipCode { get; set; }

  protected override IEnumerable<PropertyInfo> GetTypeSpecificSignatureProperties( ) {
            return typeof( SimpleAddress ).GetProperties();

We’re still missing one step to make everything work: we need to create a custom service locator. Since this is just demo code, we’re adding the simplest service locator we can create (we’re not performing any error validations and we’re only implementing the IServiceLocator’s GetService method):

public class MyServiceLocator:IServiceLocator {
    public object GetService( Type serviceType ) {
       return new SimpleAddressValidator();
   //all other methods throw NotImplementedException

The final step: configure the ServiceLocator to use our service locator. Here’s the final code that does that and sets up everything for testing purposes:

var address1 = new SimpleAddress {
                                       Street = "Street X",
                                       ZipCode = "SomethingElse"

var address3 = new SimpleAddress {
                                       Street = "",
                                       ZipCode = "DifferentAddress"

ServiceLocator.SetLocatorProvider( () => new MyServiceLocator() );
Console.WriteLine( "address 1 is valid: {0}", address1.IsValid());
Console.WriteLine( "address 3 is valid: {0}", address3.IsValid());

As I’ve said, if you’re using the NH Validator framework, then you should reuse the default implementations of these interface because that will really make all this work we’ve done unnecessary. The SharpArch.Core.NHibernateValidator assembly adds a default validator (Validator) and a default IValidationResult implementation (ValidationResult). As I’ve said, if you’re using the NH Validator framework, then you’ll only need to decorate the properties with the correct  attributes. We’ll come back to this topic on the future, when we take a deep look at the demo projects that accompany the framework.

And that’s it for today…Keep tuned for more on the S#arp framework.


~ by Luis Abreu on April 19, 2009.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: