问题
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