Self-Configuring Enterprise Library Validation

A recent project used Enterprise Library Validation to validate domain objects, and needed it configured for a web front end, a WCF front end, and (of course) unit tests. The same configuration in 3 different places didn't strike me as very DRY, so I figured hey - why not have it configure itself? Here's a quick paraphrase of how I did it.

I started with an abstraction of the validation service:

public interface IValidationService {     bool IsValid(T objectToValidate) where T : class; }

...which I implemented like so:

using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Reflection; using Microsoft.Practices.EnterpriseLibrary.Validation;

public class SelfConfiguringEnterpriseLibraryValidationService : IValidationService {     private static readonly Dictionary<Type, Validator> _validators = GetConfiguredValidators;

    public bool IsValid(T objectToValidate) where T : class     {         if (!_validators.ContainsKey(typeof(T)))         {             return true;         }

        ValidationResults results = _validators[typeof(T)].Validate(objectToValidate);

        return results.IsValid;     }

    private static Dictionary<Type, Validator> GetConfiguredValidators     {         /* Further down the page :) */     } }

...fairly straightforward: a static-scoped _validators Dictionary of Validator objects keyed by the Type of object they validate, and an implementation of IsValid which looks up the appropriate Validator, and uses it to validate the object if it exists.

The nitty gritty of this class is the GetConfiguredValidators method, which puts together the Dictionary of Validators. It uses an extension method I've mentioned before which gets all the available deployed Types, and goes a bit like this:

private static Dictionary<Type, Validator> GetConfiguredValidators {     Dictionary<Type, Validator> validators = new Dictionary<Type, Validator>;

    // Get all the available deployed Types;     IEnumerable<Type> availableTypes = Assembly.GetExecutingAssembly.GetAvailableTypes(         a => a.FullName.StartsWith("MyNamespace."), // <- only Assemblies we've written         t => !(t.IsAbstract || t.IsInterface));     // <- only concrete Types

    IEnumerable<Type> validatorTypes = availableTypes         .Where(t => typeof(Validator).IsAssignableFrom(t))         .ToArray

    validatorTypes.ForEach(vt =>     {         Type validatedType = null;

        if (vt.IsGenericType)         {             // This Validator inherits from Validator, so register it against T:             validatedType = vt.GetGenericArguments.First;         }         else         {             // This is a non-generic Validator, so I'm going to rely on a convention;             // it should be named [ValidatedType]Validator, so I can get the validated             // Type from the name:             string validatedTypeName = vt.Name.Replace("Validator", null);             validatedType = availableTypes.First(t => t.Name == validatedTypeName);         }

        // Create an instance of the Validator; Validators have a constructor which         // takes a NameValueCollection, so supply one of those:         // Instead of Activator.CreateInstance, you can use this:         // Validator validator = (Validator)vt.GetInstance")(new NameValueCollection);         Validator validator = (Validator)Activator.CreateInstance(vt, new NameValueCollection);

        validators.Add(validatedType, validator);     });

    return validators; }

I then used Unity to plug the implementation in behind the interface, and that's it.

There's a few things to note about this implementation:

  1. As per the notes, it relies on non-generic Validators following a particular naming convention
  2. It assumes each domain object Type should always be subject to the same validation; it makes no provision for Validation RuleSets
  3. It assumes there's only a single Validator Type for each validated Type

These issues could all be dealt with fairly easily using:

  1. Attributes for non-generic Validators to declare what Type they validate
  2. Attributes for Validators to label themselves as belonging to a particular Validation RuleSet
  3. A List being used as the _validators Dictionary value

It works nicely, and I was quite pleased to delete my validation config:)

This article is part of the GWB Archives. Original Author: Steve Wilkes

New on Geeks with Blogs

  • We Won The One Award I Actually Care About

    Full Scale made the Inc. 5000 for the fifth year straight, the 12th listing across my three companies. Here is why the one award you cannot buy is worth stopping for.

  • Your Customers Build the Features Now

    I let a tool I liked sit dead for a year rather than build the features I wanted. An MCP server meant I never had to, and your customers can do the same to your product.

  • Get the Size of a Directory in Linux the Easy Way

    du -sh for the quick answer, ncdu for the cleanup, df for the disk itself: every command for checking directory size in Linux, plus why du and df never agree.

  • Vim Search and Replace: The Ultimate Guide

    One :%s command replaces every match in a file before a find dialog would even open. The Vim substitute patterns worth the muscle memory: flags, ranges, capture groups, and multi-file edits.