DataAnnotations命名空间中的Enum值是否有开箱即用的验证器?

时间:2013-01-17 14:44:30

标签: c# enums data-annotations

C#枚举值不仅限于其定义中列出的值,还可以存储其基本类型的任何值。如果基本类型未定义为Int32或仅使用int

我正在开发一个WCF服务,需要确信某些枚举的值已分配,而不是所有枚举为0的默认值。我从单元测试开始,以确定[Required]是否会执行在这里工作正确。

using System.ComponentModel.DataAnnotations;
using Xunit;

public enum MyEnum
{
    // I always start from 1 in order to distinct first value from the default value
    First = 1,
    Second,
}

public class Entity
{
    [Required]
    public MyEnum EnumValue { get; set; }
}

public class EntityValidationTests
{
    [Fact]
    public void TestValidEnumValue()
    {
        Entity entity = new Entity { EnumValue = MyEnum.First };

        Validator.ValidateObject(entity, new ValidationContext(entity, null, null));
    }

    [Fact]
    public void TestInvalidEnumValue()
    {
        Entity entity = new Entity { EnumValue = (MyEnum)(-126) };
        // -126 is stored in the entity.EnumValue property

        Assert.Throws<ValidationException>(() =>
            Validator.ValidateObject(entity, new ValidationContext(entity, null, null)));
    }
}

没有,第二次测试不会抛出任何异常。

我的问题是:是否有验证属性来检查提供的值是否在Enum.GetValues

更新即可。 请务必使用ValidateObject(Object, ValidationContext, Boolean),其最后一个参数等于True,而不是{单元测试中的ValidateObject(Object, ValidationContext)

2 个答案:

答案 0 :(得分:18)

.NET4 +中有EnumDataType ...

确保在调用validateAllProperties=true

时设置第3个参数ValidateObject

所以从你的例子:

public class Entity
{
    [EnumDataType(typeof(MyEnum))]
    public MyEnum EnumValue { get; set; }
}

[Fact]
public void TestInvalidEnumValue()
{
    Entity entity = new Entity { EnumValue = (MyEnum)(-126) };
    // -126 is stored in the entity.EnumValue property

    Assert.Throws<ValidationException>(() =>
        Validator.ValidateObject(entity, new ValidationContext(entity, null, null), true));
}

答案 1 :(得分:10)

您正在寻找的是:

 Enum.IsDefined(typeof(MyEnum), entity.EnumValue)

<强> [更新+ 1]

开箱即用的验证程序执行了很多验证,包括这个验证程序称为EnumDataType。确保将validateAllProperties = true设置为ValidateObject,否则测试将失败。

如果您只想检查是否定义了枚举,可以使用上述行的自定义验证器:

    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false)]
    public sealed class EnumValidateExistsAttribute : DataTypeAttribute
    {
        public EnumValidateExistsAttribute(Type enumType)
            : base("Enumeration")
        {
            this.EnumType = enumType;
        }

        public override bool IsValid(object value)
        {
            if (this.EnumType == null)
            {
                throw new InvalidOperationException("Type cannot be null");
            }
            if (!this.EnumType.IsEnum)
            {
                throw new InvalidOperationException("Type must be an enum");
            }
            if (!Enum.IsDefined(EnumType, value))
            {
                return false;
            }
            return true;
        }

        public Type EnumType
        {
            get;
            set;
        }
    }

......但我想它不是开箱即用的呢?