question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add documentation for validating abstract class implemenetations

See original GitHub issue

Is 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:closed
  • Created 8 months ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
JeremySkinnercommented, Feb 7, 2023

Yes, use IncludeProperties to only validate specific properties on the root validator:

validator.Validate(model, options => {
  options.IncludeProperties("Elements");
});
0reactions
JeremySkinnercommented, Feb 8, 2023

Yep, that approach is fine and works well. Alternatively you can use Include statements if you prefer composition to inheritance

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documenting my abstract class/interface - what is important?
For creating a new invoice for instance, I get some data off the screen, I validate any values that might not be good...
Read more >
Using abstract base class for documentation purposes only
My example simplifies quite a bit, in fact, I need the Executors to be classes because they hold some state. – arne. Mar...
Read more >
Compile-time abstract class validation for Swift
Based on the classes data models, it then validates the implementations against the abstract class rules. Rules include abstract classes cannot be directly ......
Read more >
Abstract Class Design - Framework Design Guidelines
Doing this helps to validate the design of the abstract class. For example, System.IO.FileStream is an implementation of the System.IO.
Read more >
Validate property is a subclass of an abstract class
I can see that Matlab is attempting to assign a default value to myProperty which is an empty instance of myAbstractClass.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found