Dariel
Dariel

Reputation: 77

How can I validate an enum in FluentValidator C#

I am creating a validation class using FluentValidation in C#, to validate that my Type property of Account class is of type AccountType enum.

What would be the correct implementation of this:

RuleFor (account => account.Type)
             .IsInEnum (....)

Upvotes: 4

Views: 8097

Answers (2)

Brandon Manchester
Brandon Manchester

Reputation: 5013

I asked myself the same thing, then I googled it and found your question here. That didn't help very much. It did however make me go looked at the source and unit tests on github so thanks for that. https://github.com/JeremySkinner/FluentValidation/blob/master/src/FluentValidation.Tests/EnumValidatorTests.cs

I'm putting this here for the next person that comes along with the same question. You do not need to provide any implementation to the IsInEnum() function. This function uses reflection to determine the Enum type of the property specified in your rule, and then validates the value of that property based on valid values of the Enum.

Upvotes: 3

InBetween
InBetween

Reputation: 32760

You could do the following:

public static bool IsDefinedInEnum(this Enum value, Type enumType)
{
    if (value.GetType() != enumType)
        return false;

    return Enum.IsDefined(enumType, value);
}

The code can use some explanation:

  • The first check simply makes sure that the value of the enumeration and the type of the enumeration are the same. If they are not, the method must return, obviously, false. But why is this necessary? Enum.IsDefined would cover this too, right?

    Ideally, we'd want a method with the following signature: IsDefinedIn<T>(this T value) where T: Enum. This would be totally type safe at compile time but, sadly, the constraint T: Enum is not valid. This means that enumType can be anything, like typeof(object), there is no mechanism in the language to constraint enumType to only enumeration types. This can make Enum.IsDefined throw, if you don't want this happening, you should keep the first check.

    Do consider that you should throw (or assert) if passing some type that is not an Enum is a bug in your code. I've just shown you how you could get around this issue if necessary.

  • The second check simply makes sure the value is defined in the enumeration. SomeEnumeration.SomeValue would return true and (SomeEnumeration)5 would return false unless there is a member of the enumeration with that value.

Upvotes: 2

Related Questions