This project is read-only.

ValidatorFactory

A validator factory will have to implement following interface:

public interface IValidatorFactory
{
    /// <summary>
    /// Registers the specified validator type.
    /// <para>If a validator is registered as default, it will be resolvable when the client call "GetValidatorFor".</para>
    /// </summary>
    void Register<T>(bool isDefault = false) where T : class, IValidator;

    /// <summary>
    /// Registers the specified validator type.
    /// <para>If a validator is registered as default, it will be resolvable when the client call "GetValidatorFor".</para>
    /// </summary>
    void Register<T>(T validator, bool isDefault = false) where T : class, IValidator;

    /// <summary>
    /// Resolves any registered validator include none-default one.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    T Resolve<T>() where T : class, IValidator;
    
    /// <summary>
    /// Determines whether the validator type is registered as default validator.
    /// </summary>
    bool IsDefaultValidator<T>() where T : class, IValidator;
    
    /// <summary>
    /// Determines whether the validator type is default validator.
    /// </summary>
    bool IsDefaultValidator(Type validatorType);

    /// <summary>
    /// Gets the "DEFAULT" validator for a type.
    /// <para>Only validator registered as default will be returned.</para>
    /// </summary>
    IValidator GetValidatorFor(Type objectType);

    /// <summary>
    /// Gets the "DEFAULT" validator for a type.
    /// <para>Only validator registered as default will be returned.</para>
    /// </summary>
    IValidator<T> GetValidatorFor<T>() where T : class;
}

There is a default implementation of this interface and ready for use so most of cases, you will not need to implement a custom validator factory. Basically, a validator factory will have following responsibilities:
  • Register a validator type/instance
  • Resolve a valiator by validator type
  • Check if a validator type is default
  • Get validator for a business object

As mentioned in previous topics, any custom validator has to be registered with the factory. If a validator is registered as default, it can be returned when we use validator factory to get the validator for a business object. It's very important since this logic is used in CompositeValidator<T> class when it tries to validate nested complex type properties. Therefore, if you're implementing a custom validator factory using your way, please follow this logic.

The resolve method is used only for the internal LazyValidator<T> class which intern is used when we call method SetValidator<T> in the chain. That means if we use SetValidator<T> somewhere without registering the T validator type with the factory, it's gonna cause problem since Resolve requires that the validator has been registered before.

The methods that check a validator type is default or not are important as I mentioned. And finally, those methods that are used to get validator for a business object type are the most important methods. There is a little fancy implementation here when it try to get validators for a base type and a derived type.
For example, we have class Organisation as the base class and Company as the derived class, and we have custom validator for Organisation and Company as well. Those custom validators certainly are registered with validator factory. So when we get validator for Organisation, it's a must to return OrganisationValidator, and when getting validator for Company, it should return CompanyValidator.

And if there is only OrganisationValidator is registered to the factory, that validator should be returned when we get validator for Organisation or Company. This behavior is quite confused so in order to avoid that, we either should not use inheritance in business objects or call SetValidator<T> manually on the complex property.

The default validator is implemented using the internal collection to remember all the types and instances that are registered against it. There are quite a few unit tests to ensure that the behavior i described above work as expected. If you wish to make your own validator factory, for dependency injection purpose for instance, please replace the ValidatorFactory.Current value in the very beginning of your application. There will be another topic about validator factory with IOC but in the scope of this topic, I just want to emphasis the behavior of the default validator factory.

In the mean time, the validator factory return only 1 validator for a business object type. I still have no idea why we need more than 1 validator for a business object but potentially there would be a good reason for that. Then it will be the next release of this library :)

Last edited Dec 23, 2011 at 3:18 AM by nvthoai, version 3

Comments

No comments yet.