This project is read-only.

ValidationBuilder

As I mentioned in the project description, I implemented NValidator using Chain Of Responsibility pattern and ValidationBuilder is the core of the it. Basically, a ValidationBuilder contains an IValidator object, it has 2 references to the next builder and previous builder in the chain. A TypeValidator or CompositeValidator in turn contain a list of ValidationBuilder so when the type validator is used to validate some object, it will call validate method on everysingle validation builder in the list, start from the first builder of the chain to the last one.


A ValidationBuilder implements following interfaces:

public interface IHaveContainer
{
	string ContainerName { get;}
	void UpdateContainerName(string containerName);
}
	
public interface IChainOfValidationBuilder<T>
{
    IValidationBuilder<T> Next { get; set; }
    IValidationBuilder<T> Previous { get; set; }
    bool StopChainOnError { get; set; }
    string ChainName { get; set; }
}

public interface IValidationBuilder<T> : IChainOfValidationBuilder<T>, IHaveContainer
{
    IValidator Validator { get; set; }
    IValidationBuilder<T> SetValidator(IValidator validator);
    IEnumerable<ValidationResult> Validate(T container, ValidationContext validationContext);

    Action<IValidationBuilder<T>, ValidationContext> BeforeValidation { get; set; }
    Func<IValidationBuilder<T>, IEnumerable<ValidationResult>, IEnumerable<ValidationResult>> AfterValidation { get; set; }
}

public interface IValidationBuilder<T, TProperty> : IValidationBuilder<T>,
                                                    IPostInitFluentValidationBuilder<T, TProperty>,
                                                    ICloneable
{
    Expression<Func<T, TProperty>> Expression { get; set; }
}
  • IHaveContainer: this interface provides method and property to allow the container object, could be a validator or a validation builder to get and set the container name. For example, we specify following rules:
public UserValidator : TypeValidator<User>
{
    public UserValidator()
    {
        RuleFor(x => x.Address)
            .NotNull()
            .SetValidator<AddressValidator>();
    }
}
In the above example, UserValidator is a TypeValidator object, it has a list contains 1 validation builder for property Address. Actually, the first validation builder has the validator type NotNullValidator and that builder link to the next validation builder which has a validator of type AddressValidator. In the other words, there is a chain of 2 validation builders. Once the UserValidator is used to validate, it will perform validation on NotNull rule first and after that, go to AddressValidator. If AddressValidator is a TypeValidator<Address>, then it definitely inherits members of IHasContainer from the base type. The validation builder will update the container name before using its validator for validation. The ContainerName in the above example would be User.Address.
  • IChainOfValidationBuilder<T>: provides memebers to access information about the chain of validation builders.
  • IValidationBuilder<T>: providate the basic members of a valition builder such as Validator, Validate(), etc
  • IValidationBuilder<T, TProperty>: providate the expression to target the property that the validation builder will validate.
  • A validation builder also implement ICloneable, and 3 IFluentValidationBuilder interfacees. Those 3 interfaces are responsible for hiding unneccesary members when I build the fluent interface for the rules.

There is one concrete validation builder that we can use: ValidationBuilder class. This class contain core logic for a builder so if you are opened to inherit from this class and make your custom implementation by overriding some of the virtual methods. Class ValidationBuilder, TypeValidator and CompositeValidator have a mechanism to clone a new builder and add to the chain while we're adding rules and the default type for validation builder is typeof(ValidationBuilder<, >). There are 2 ways to change the default type of validation builder:
  • Modify the property DefaultBuilderType of TypeValidator at the first line the constructor, this way will affect only that validator.
  • Change the global builder type at ValidatorFactory.DefaultValidationBuilderType, this way will change the default validation buider type for all TypeValidator and CompositeValidator unless we use the above method to override it





Last edited Dec 13, 2011 at 9:54 PM by nvthoai, version 2

Comments

No comments yet.