Brendan Enrick's Blog

Daily Software Development.


Validating Entity objects

by Brendan Enrick Wednesday, January 21 2009 14:22

While working with an entity object I wanted to validate, I took some time to do some Googling. I was planning on creating an IValidator<T> interface so I could keep the validation separate from my classes, and I was going to implement this interface for every entity that needed it. Since validation is pretty common I figured I would take a look around first to see if there were some good ways of performing validation which differed slightly from how I had done things previously or offered any insight on a good solution similar to what I mention above. I found a link to a blog post that had exactly what I was looking for. It turns out that Jimmy Bogard already had a great post on this topic. His post, Entity validation with visitors and extension methods, demonstrates a very cool IValidator implementation.

He combines a couple of cool interfaces to get this working. He uses an IValidator<T> interface like I mentioned I wanted to use. His implementation of this is pretty nice. (I made a slight adjustment to it here, because his example code had a bug.)

public class OrderPersistenceValidator : IValidator<Order>
{
    public bool IsValid(Order entity)
    {
        return BrokenRules(entity).Count() == 0;
    }

    public IEnumerable<string> BrokenRules(Order entity)
    {
        if (entity.Id < 0)
            yield return "Id cannot be less than 0.";

        if (string.IsNullOrEmpty(entity.Customer))
            yield return "Must include a customer.";

        yield break;
    }
}

 

I look at this an see a fairly nice and elegant solution to the validation problem. He also has an IValidatable<T> interface he uses, which is nice because it sets up a method to pass in the IValidator to use.

public class Order : IValidatable<Order>
{
    public int Id { get; set; }
    public string Customer { get; set; }

    public bool Validate(IValidator<Order> validator, out IEnumerable<string> brokenRules)
    {
        brokenRules = validator.BrokenRules(this);
        return validator.IsValid(this);
    }
}

So I think this code is pretty cool, but the only thing that was still irking me about this code is that now I would have to pass the IValidator object in to the Validate method of the entity. I really don't want to have to pass those in, so I start thinking about how to get around that problem. Well then I just read a little further in his article. He has a very nice solution to this problem using an extension method on a Validator class. (I adjusted this snippet slightly also, because it too had a bug.)

public static class Validator
{
    private static Dictionary<Type, object> _validators = new Dictionary<Type, object>();

    public static void RegisterValidatorFor<T>(T entity, IValidator<T> validator)
        where T : IValidatable<T>
    {
        _validators.Add(entity.GetType(), validator);
    }

    public static IValidator<T> GetValidatorFor<T>(T entity)
        where T : IValidatable<T>
    {
        return _validators[entity.GetType()] as IValidator<T>;
    }

    public static bool Validate<T>(this T entity, out IEnumerable<string> brokenRules)
        where T : IValidatable<T>
    {
        IValidator<T> validator = Validator.GetValidatorFor(entity);

        return entity.Validate(validator, out brokenRules);
    }
}

 

This Validator class reminds me a lot of IOC stuff. You register a validator with the entity type it validates. This lets you set up which validators each class needs so you don't have to specify on use. It also provides a nice extension method which allows you to call the validate method without having to pass in the correct validator. It will use the one it has registered for that entity type.

Great solution in my opinion. Now I am going to add his blog to the blogs I read. I hope some of you do also.

Tagged as:

Comments

1/22/2009 10:36:04 PM #

You've been kicked (a good thing) - Trackback from DotNetKicks.com


Comments are closed