Add documentation for validating abstract class implemenetations
See original GitHub issueIs your feature request related to a problem? Please describe.
I have a class which holds a List of an abstract class. For example:
public class Form
{
public List<FormElement> Elements { get; set; } = new();
}
public abstract class FormElement
{
public string Name { get; set; } = string.Empty;
public abstract string GetDefaultName();
}
public class FormNumberElement : FormElement
{
public int MinValue { get; set; }
public override string GetDefaultName() => "Number";
}
public class FormDateElement : FormElement
{
public DateTime MinDate { get; set; }
public override string GetDefaultName() => "Date";
}
The real object now hold different implementations of this abstract class. For example FormNumberElement
and FormDateElement
Now I want to split my validation into pieces because I do not want to repeat the name validation in every validator again. So i’ve created an abstract Validator for the abstract class FormElement
public abstract class FormElementValidator<T> : AbstractValidator<T> where T : FormElement
{
public FormElementValidator()
{
RuleFor(x => x.Name)
.Must(ValidateName)
.WithMessage("Please enter a name for the element");
}
private bool ValidateName(FormElement element, string name)
{
if (name == element.GetDefaultName())
{
return false;
}
return true;
}
}
Now I add two more validators for the other classes.
public class FormNumberElementValidator : FormElementValidator<FormNumberElement>
{
public FormNumberElementValidator() : base()
{
RuleFor(x => x.MinValue)
.GreaterThan(10);
}
}
public class FormDateElementValidator : FormElementValidator<FormDateElement>
{
public FormDateElementValidator() : base()
{
RuleFor(x => x.MinDate)
.GreaterThan(DateTime.Now);
}
}
Now I want to validate my List<FormElement>
and use the correct validator for the corresponding object within my list. So if my item is of type FormNumberElement
then I’ll want to use the FormNumberElementValidator
and when it’s of type FormDateElement
I’ll want to use the FormDateElementValidator
.
To achive this I’ve added an abstract method to my FormElement
class which returns an IValidator
public abstract IValidator GetValidator();
Each implementation of FormElement
returns the corresponding validator. For example within FormNumberElement
I have:
public override IValidator GetValidator() => new FormNumberElementValidator();
Now I can loop through all my elements in my List like this:
Form form = new Form();
form.Elements.Add(new FormNumberElement());
form.Elements.Add(new FormDateElement());
foreach (var element in Input.GetElements())
{
IValidator validator = element.GetValidator();
IValidationContext context = new ValidationContext<FormElement>(element);
if (validator.Validate(context).IsValid)
{
Console.Writeline($"element is valid");
}
else
{
Console.Writeline($"element is not valid");
}
}
This works exactly as I expect it. The base validation is done and the validation for the corresponding object is done as well. However, I didn’t find any documentation within the docs to truely inherit one validator to another validator in abstract context.
My suggestion is to add an explanation of this to the official docs since it took me quite some time to figure this out. I don’t know though if this works as well with DI.
Describe the solution you’d like
Please add documentation for validating a List which holds abstract items. The items in the list should be validated by the right validator implementation.
Describe alternatives you’ve considered
No response
Additional Context
No response
Issue Analytics
- State:
- Created 8 months ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
Yes, use
IncludeProperties
to only validate specific properties on the root validator:Yep, that approach is fine and works well. Alternatively you can use Include statements if you prefer composition to inheritance