19

C#列挙型の値は、その定義にリストされている値だけに限定されるものではなく、その基本型の任意の値を格納できます。基本タイプが定義されていない場合、Int32または単にint使用されている場合。

[Required]私は、いくつかの列挙型に0のすべての列挙型のデフォルト値ではなく値が割り当てられていることを確信する必要があるWCFサービスを開発しています。ここで正しい仕事をするかどうかを調べるために単体テストから始めます。

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

そうではなく、2番目のテストは例外をスローしません。

私の質問は:提供された値がにあることを確認するためのバリデーター属性はありEnum.GetValuesますか?

更新します。ユニットテストで行ったようにではなく、必ずValidateObject(Object, ValidationContext, Boolean)最後のパラメータが等しいで使用してください。TrueValidateObject(Object, ValidationContext)

4

3 に答える 3

30

.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));
}
于 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 に答える