Should i create a new Type for Collection in FluentValidation?

大城市里の小女人 提交于 2019-12-07 07:13:05

问题


I am trying to find if there is way available in FluentValidation which allows a collection to be validated for a Validator at Root Level.

For e.g. As shown below, a validator is available for CustomerValidator for a class Customer. using FluentValidation;

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);

bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;

The question is, If i have a List<Customer> and i need to validate that atleast one customer should have Surname how do i validate the list. Is there a out of box functinality available in fluentvalidation, at this time, i can think either of following ways. Can you suggest what can be best approach ?

1. Iterating in a loop and then calling the validate method for each Customer.

 List<ValidationResult> listOfValidationErrors = List<ValidationResult>();
 // listCustomer is of type List<Customer>
 foreach (var customer in listCustomer)
 {
     CustomerValidator validator = new CustomerValidator();
     listOfValidationErrors.Add(validator.Validate(customer);
 }

2. Create a new collection class for Customer collection CustomerCollection and then create a validator class CustomerCollectionValidator

    public class CustomerCollection
    {
        public List<Customer> ListOfCustomers { get; set; }

        public CustomerCollection(List<Customer> listOfCustomers )
        {
            this.ListOfCustomers = listOfCustomers ;
        }
    }

and then Validator class

public class CustomerCollectionValidator: CompositeValidator<CustomerCollection>
    {
        public CustomerCollectionValidator()
        {

            RuleFor(x => x.ListOfCustomers)
                    .Must(ShouldHaveOneSurName)
                    .WithMessage("Should have one Surname in list");

            RuleForEach(x => x.ListOfCustomers).SetValidator<CustomerValidator>();

        }

        public bool ShouldHaveOneSurName(List<Customer> lstCustomers)
        {
            if (lstCustomers== null)
            {
                return false;
            }
            return lstCustomers.Any(x => !String.IsNullOrWhiteSpace(x.SurName);
        }


    }

回答1:


Apart from the above 2 methods, Jeremy Skinner suggested another method here, which uses inheritance from AbstractValidator<List<Customer>> . This didn't work with original code, but Jeremy committed the change in Fluent Validation source code in version 6.3 here.

Following code presents the 3rd way for doing the validation for Root Level collection.

public class CustomerCollectionValidator : AbstractValidator<List<Customer>> {
  public CustomerCollectionValidator() {
     RuleFor(list => list).SetCollectionValidator(new CustomerValidator());
  }
}


来源:https://stackoverflow.com/questions/36658385/should-i-create-a-new-type-for-collection-in-fluentvalidation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!