Reputation: 77
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
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
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