如何使用数据注释处理 C# 中的枚举并使用 XUnit 对其进行测试

How to handle Enums in C# with Data Annotations and testing it with XUnit

我想限制我的 DTO 的值。

我有几个月的枚举:

public enum Month
{
    January,
    February,
    March,
    May,
    June,
    July,
    August,
    September,
    October,
    November,
    December
}

现在在我的 DTO 中我有:

public class MyDTO {
    public Month Month{ get; set; }
}

我需要使用数据注释来仅接受从 MarchOctober,并对其进行测试。 Xunit 作为 https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-dotnet-test

[Fact]
public void valid DTO_Months_ok()
{
    var dto = MyDTO()
    {
        Month = Month.March
    }
    var result = dto.validate();
    Assert.Equal(0, result.Count);
}

并检查错误

[Fact]
public void valid DTO_Months_Error()
{
    var dto = MyDTO()
    {
        Month = Month.February
    }
    var result = dto.validate();
    Assert.Equal(1, result.Count);
}

我的问题是 DataAnnotation。

如何使用 Enum 的 DataAnnotation?

恕我直言,这看起来有点“hacky”。 DataAnnotations 是应用于 属性 of class 的规则,以防止输入无效值。这确认该值将始终有效。通常它应用于“太大”和“可以输入的值不同”的值。例如 [StringLength(50, MinimumLength = 3)] 限制 string.

的长度

在枚举的情况下:您不想使用从 MarchOctober 的其他值,那么为什么将它们保留在枚举本身中?从这个问题看来,你只想拥有这些价值观,所以它有意义:

public enum RestrictedMonth
{
    March,
    May,
    June,
    July,
    August,
    September,
    October,
}

无论如何,如果这对你来说还不够,你可以定义你的 custom data annotations with params as array:

public class EnumInRangeAttribute : ValidationAttribute
{
    public Month[] ValidMonths { get; set; }

    public EnumInRangeAttribute()
    {
        ValidMonths = new Month[0];
    }

    public EnumInRangeAttribute(params Month[] ValidMonths)
    {
        this.ValidMonths = ValidMonths;
    }

    public override bool IsValid(object value)
    {
        if (value is Month monthValue)
        {
            return ValidMonths.Contains(monthValue);
        }
        return true;
    }
}

public class MyDTO {
    [EnumInRange(Month.March,
        Month.May,
        Month.June,
        Month.July,
        Month.August,
        Month.September,
        Month.October)]
    public Month Month { get; set; }
}