Spent a day on searching an answer.
I have the following validator (please note that there are different rules for AgeMin property depends on RuleSet.):
class WeirdValidator : AbstractValidator<TestClass>
{
public WeirdValidator()
{
public const string CustomRuleSet = nameof(CustomRuleSet);
RuleFor(instance => instance.AgeMin).NotEmpty().WithMessage("Empty error. {PropertyName}").ScalePrecision(2, 3).WithMessage("Scale error. {PropertyName}");
RuleFor(instance => instance.FirstInt).NotEmpty().WithMessage("Empty error. {PropertyName}");
RuleSet(CustomRuleSet, () => {
RuleFor(instance => instance.AgeMin).Empty().WithMessage("{PropertyName} must be empty.");
RuleFor(instance => instance.SecondInt).NotEmpty().WithMessage("{PropertyName} must not be empty.");
});
}
}
and the following test class:
class TestClass
{
public decimal AgeMin { get; set; }
public int FirstInt { get; set; }
public int SecondInt { get; set; }
}
FluentValidation allows us to combine validators:
var result = validator.Validate(instanceToValidate, opt => {
opt.IncludeRuleSets(WeirdValidator.CustomRuleSet);
opt.IncludeProperties(nameof(instanceToValidate.AgeMin));});
But it does not work as I expected. it is not intersection of rules, but consequent actions: at first applying all rules from CustomRuleSet and then rule for defined property. I need validation of only selected property of only selected ruleset. I am sure that there is a very simple and elegant solution but it does not illuminate my way yet.
Question: How to validate a specific property within a specific ruleset?
After several days of pain and tears I found a very bad looking solution but, nevertheless, working.
var validator = new WeirdValidator();
var ruleDescriptor = validator.CreateDescriptor();
var rulesOfMember = ruleDescriptor.GetRulesForMember(nameof(instanceToValidate.AgeMin));
var exactRule = rulesOfMember.FirstOrDefault(c => c.RuleSets.Contains(WeirdValidator.CustomRuleSet));
var errorList = exactRule.Validate(
new ValidationContext<TestClass>(instanceToValidate, new PropertyChain(),
new RulesetValidatorSelector(WeirdValidator.CustomRuleSet)));
The main idea was to find the exact rule for exact property and to execute only one. It turned out that IValidationRule has own Validate/ValidateAsync methods.
If someone knows better/more elegant solution, you are welcome.