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; }
}
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.

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: