1

Wondering is there a possibility to avoid writing rules for every fields that needs to get validated, for an example all the properties must be validated except Remarks. And I was thinking to avoid writing RuleFor for every property.

public class CustomerDto
{
    public int CustomerId { get; set; }         //mandatory
    public string CustomerName { get; set; }    //mandatory
    public DateTime DateOfBirth { get; set; }   //mandatory
    public decimal Salary { get; set; }         //mandatory
    public string Remarks { get; set; }         //optional 
}

public class CustomerValidator : AbstractValidator<CustomerDto>
{
    public CustomerValidator()
    {
        RuleFor(x => x.CustomerId).NotEmpty();
        RuleFor(x => x.CustomerName).NotEmpty();
        RuleFor(x => x.DateOfBirth).NotEmpty();
        RuleFor(x => x.Salary).NotEmpty();
    }
}
Coder Absolute
  • 5,417
  • 5
  • 26
  • 41

1 Answers1

3

Here you go:

public class Validator<T> : AbstractValidator<T>
{
    public Validator(Func<PropertyInfo, bool> filter) {
        foreach (var propertyInfo in typeof(T)
            .GetProperties()
            .Where(filter)) {
            var expression = CreateExpression(propertyInfo);
            RuleFor(expression).NotEmpty();
        }
    }

    private Expression<Func<T, object>> CreateExpression(PropertyInfo propertyInfo) {
        var parameter = Expression.Parameter(typeof(T), "x");
        var property = Expression.Property(parameter, propertyInfo);
        var conversion = Expression.Convert(property, typeof(object));
        var lambda = Expression.Lambda<Func<T, object>>(conversion, parameter);

        return lambda;
    }
}

And it can be used as such:

    private static void ConfigAndTestFluent()
    {
        CustomerDto customer = new CustomerDto();
        Validator<CustomerDto> validator = new Validator<CustomerDto>(x=>x.Name!="Remarks"); //we specify here the matching filter for properties
        ValidationResult results = validator.Validate(customer);
    }
Tamas Ionut
  • 4,240
  • 5
  • 36
  • 59