Denis Pitcher
Denis Pitcher

Reputation: 3240

Greater than or equals comparison against an enum with Fluent Validation?

Ok, let's say I'm trying to validate an object conditionally based upon the value of an enum, how can I do that?

Here's a sample call to validate the object.

MyObjectValidator validator = new MyObjectValidator();
ValidationResult results = validator.Validate(new MyObject());

Here's a sample of a class with an Enum Value.

public class MyObjectValidator : AbstractValidator<MyObject>
{

    public MyObjectValidator()
    {
        RuleFor(x => x.anEnum).Equal(MyObject.MyEnum.First).SetValidator(new FirstValidator());
    }

}

public class FirstValidator : AbstractValidator<MyObject>
{

    public FirstValidator()
    {
        RuleFor(x => x.someDecimal).Equal(1).WithMessage("Decimal must equal 5 with anEnum set to First");
    }

}

public class MyObject
{

    public enum MyEnum : int
    {
        First = 0,
        Second = 1,
        Third = 2
    }

    public decimal someDecimal { get; set; }
    public MyEnum anEnum { get; set; }

    public MyObject()
    {
        anEnum = MyEnum.First;
        someDecimal = 5;
    }
}

This particular example throws the message: "The validator 'FirstValidator' cannot validate members of type 'MyEnum' - the types are not compatible."

After some editing, I came up with a wrapper to do what I'm hoping, but I'd prefer a more elegant solution. I replaced MyObjectValidator with

public MyObjectValidator()
{
    RuleFor(x => x.anEnum).SetValidator(new ValidatorWrapper<MyObject>()).When(x => x.anEnum == MyObject.MyEnum.First);
}

And added a validator wrapper

public class ValidatorWrapper<T> : PropertyValidator
{

    public ValidatorWrapper() : base("Validator Message")
    {
    }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        MyObject myObj = (MyObject)context.Instance;
        FirstValidator validator = new FirstValidator();
        ValidationResult results = validator.Validate(myObj);
    }
}

Is there a way to reference the inner context without having to provide the propertyvalidator wrapper such that I can conditionally validate a number of rules based upon an enum value?

Upvotes: 3

Views: 4533

Answers (2)

Jeremy Skinner
Jeremy Skinner

Reputation: 1461

The error you're seeing ("The validator 'FirstValidator' cannot validate members of type 'MyEnum' - the types are not compatible") is because by using SetValidator you're trying to validate the anEnum property with FirstValidator (which can only validate instances of MyObject) - this isn't the correct approach. If you want to trigger rules based on the enum property, you need to use FluentValidation's support for conditions.

If you've only got a single rule to which you want to apply the condition, then you can do this:

public class MyObjectValidator : AbstractValidator<MyObject> {

  public MyObjectValidator() {
      RuleFor(x => x.someDecimal).Equal(1).When(x => x.anEnum == MyObject.MyEnum.First);
  }

}

...alternatively, if you want to apply the same condition to multiple rules, you can use a single condition using the top-level When method:

public class MyObjectValidator : AbstractValidator<MyObject> {

    public MyObjectValidator() {
        When(x => x.anEnum == MyObject.MyEnum.First, () => {
            RuleFor(x => x.someDecimal).Equal(1);
            //other rules can go here
        });
    }

}

Upvotes: 5

kprobst
kprobst

Reputation: 16651

You're using the CLR's Object.Equals(), you need to use Equal() or whatever else the library provides.

Upvotes: 0

Related Questions