Reputation: 20995
I'm trying to filter arguments to use in a collection validator using FluentValidations:
I have a generic Class for Collections which looks like:
public class ItemCollection<TEntity>
{
public ItemCollection(TEntity[] items);
public TEntity[] Items { get; }
}
I have a Validator for my ItemCollection which looks like so:
public FooCollectionValidator: AbstractValidator<ItemCollection<Foo>>
{
public FooCollectionValidator(IDictionary<string, FooMetadata> allowedMetadata)
{
//Setting Rules using Must works fine
this.RuleForEach(x => x.Items).Must(x => allowedMetadata.ContainsKey(x.Key));
}
}
I Need to set a Validator For each on of the Item but I would like to filter my Metadata For the Child Validator No matter what way I try I don't have access to the items to be able to filter:
this.RuleForEach(x => x.Items).SetValidator(x =>
{
//I want to filter the metadata by the Key and pass it to the child validator
var metadata = allowedMetadata[x.Key];
return new FooDTOValidator(metadata )
});
This Doesn't work because X always refers to the collection and not the individual item. How can I filter arguments passed to a collection validator?
Upvotes: 0
Views: 1251
Reputation: 1671
I fumbled a bit around and it does not seem possible with SetValidator
. SetCollectionValidator
as suggested is or will be deprecated.
The only way I can think of is this:
this.RuleForEach(x => x.Items).Must(x =>
{
var validator = new FooDTOValidator(allowedMetadata[x.Key]);
return validator.Validate(x).IsValid;
});
Edit As noted in the comment we loose our error messages. There might be a chance to preserve them. Take this as not tested but according to the docs we can get the Root Context Data and add our failures if any.
this.RuleForEach(x => x.Items).Custom((x, context) =>
{
var validator = new FooDTOValidator(allowedMetadata[x.Key]);
var result = validator.Validate(x);
if (!result.IsValid)
{
foreach (var failure in result.Errors)
{
context.AddFailure(failure);
}
}
});
Upvotes: 2