Quantcast
Channel: Fluent Validation for .NET
Viewing all articles
Browse latest Browse all 1917

New Post: Get index in a collection as nested property

$
0
0

Unfortunately you can't actually inherit from the adaptor - the way it's currently designed means that you need to re-implement most of the logic (something I'm going to investigating changing in a future release). Here's an example of a custom validator that should hopefully do what you're after:

public class CustomProfessorValidator : NoopPropertyValidator {
	public override IEnumerable<Results.ValidationFailure> Validate(PropertyValidatorContext context) {
		context.MessageFormatter.AppendPropertyName(context.PropertyDescription);
			
		var school = (School)context.Instance;
		var budget = school.Budget;
		var maxSalary = budget / 100;

		var professors = context.PropertyValue as IList<Professor>;
		if (professors == null || professors.Count == 0) yield break; //skip validation for empty list

		int count = 0;

		foreach(var professor in professors) {
			if (professor == null) {
				count++;
				continue;
			}

			//create a new context for each professor

			if(professor.Salary > maxSalary) {
				var newChain = new PropertyChain(context.ParentContext.PropertyChain);
				newChain.Add(context.Rule.Member);
				newChain.AddIndexer(count++);
				yield return new ValidationFailure(newChain.ToString(), "Salary must be smaller than 1% of budget.", professor.Salary);
			}
			else {
				count++;
			}
		}

	}

}

Example usage:

public class School {
	public decimal Budget { get; set; }
	public Faculty Faculty { get; set; }
}

public class Faculty {
	public IList<Professor> Professors { get; set; }
}

public class Professor {
	public decimal Salary { get; set; }
}

public class SchoolValidator : AbstractValidator<School> {
	public SchoolValidator() {
		RuleFor(x => x.Faculty.Professors).SetValidator(new CustomProfessorValidator());
	}
}

var school = new School {
	Budget = 3000000,
	Faculty = new Faculty {
 		Professors = new List<Professor> {
			new Professor { Salary = 30000 },//valid
			new Professor { Salary = 40000 }, //invalid
 		}
 	}
};

var result = new SchoolValidator().Validate(school);
  foreach(var error in result.Errors) {
	Console.WriteLine(error.PropertyName + " - " + error.ErrorMessage);
  }
}

It's not the most elegant solution - with FV 3.3 I hope to enhance collection validators to support greater contextual information about the parent instance being validated.

Jeremy


Viewing all articles
Browse latest Browse all 1917

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>