19

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)在我的单元测试中使用。

4

3 回答 3

30

.NET4+ 中有EnumDataType ...

validateAllProperties=true确保在调用中设置了第三个参数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));
}
于 2013-01-17T15:03:19.373 回答
11

您正在寻找的是:

 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;
        }
    }

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

于 2013-01-17T14:47:00.050 回答
1

我只是根据这个网站https://kristinaalberto.com/making-enum-parameters-required-in-asp-net-core-mvc/解决了我的需求

    public enum CreatedBySelfOrOthersEnumValues
    {
        Self,
        Others
    }

  
    public class CampaignRegisterValidationModel
    {
        [Required]
        public string Name { get; set; }

        [Required]
        public CreatedBySelfOrOthersEnumValues CreatedForSelfOrOthers { get; set; }

        [Required]
        public int CountryCode { get; set; }

        public string Phone { get; set; }
        public string Email { get; set; }
    }

然后验证

     if (ModelState.IsValid)
     {
     }
于 2021-05-23T08:35:11.967 回答