.NET 7选项模式下,能否为集合内值添加数据验证注解?
问题描述
在采用选项模式的.NET 7应用中,能否为集合内的元素而非集合本身添加数据注解?我有一个接收枚举值列表的配置,希望添加EnumDataType注解以限制仅允许合法枚举值,但直接将注解添加到List属性上时,验证失败并提示‘The field Days is invalid.’,以下是最小复现示例:
using System.ComponentModel.DataAnnotations; var c = new MyConfig(); Validator.ValidateObject(c, new ValidationContext(c), true); class MyConfig { [EnumDataType(typeof(DayOfWeek))] public List<DayOfWeek> Days { get; set; } = new() { DayOfWeek.Monday }; }
解决方案
直接给List<T>类型的属性加EnumDataType注解行不通,因为这个注解是用来验证单个值的,无法作用于集合整体。要实现集合元素的枚举验证,有两种实用方法:
方法1:自定义集合验证属性
创建继承自ValidationAttribute的自定义属性,遍历集合元素逐一验证枚举合法性:
using System.ComponentModel.DataAnnotations; using System.Linq; class EnumCollectionAttribute : ValidationAttribute { private readonly Type _enumType; public EnumCollectionAttribute(Type enumType) { _enumType = enumType; if (!_enumType.IsEnum) { throw new ArgumentException("指定的类型必须是枚举"); } } protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { if (value is not IEnumerable<object> collection) { return ValidationResult.Success; // 空值或非集合按需求处理,此处视为有效 } var invalidItems = collection .Where(item => !Enum.IsDefined(_enumType, item)) .ToList(); if (invalidItems.Any()) { return new ValidationResult($"集合中包含无效的{_enumType.Name}值:{string.Join(", ", invalidItems)}"); } return ValidationResult.Success; } }
在配置类中使用该自定义属性:
class MyConfig { [EnumCollection(typeof(DayOfWeek))] public List<DayOfWeek> Days { get; set; } = new() { DayOfWeek.Monday }; }
方法2:实现IValidatableObject手动验证
让配置类实现IValidatableObject接口,在自定义验证逻辑中遍历集合元素逐个校验:
using System.ComponentModel.DataAnnotations; using System.Linq; class MyConfig : IValidatableObject { public List<DayOfWeek> Days { get; set; } = new() { DayOfWeek.Monday }; public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { if (Days == null) yield break; var enumValidator = new EnumDataTypeAttribute(typeof(DayOfWeek)); foreach (var day in Days) { var result = enumValidator.GetValidationResult(day, validationContext); if (result != ValidationResult.Success) { yield return new ValidationResult($"Days中的值{day}不是有效的DayOfWeek枚举值", new[] { nameof(Days) }); } } } }
选项模式中启用验证
在.NET 7的选项模式配置中,要确保开启数据注解验证,示例如下:
builder.Services.AddOptions<MyConfig>() .Bind(builder.Configuration.GetSection("MyConfig")) .ValidateDataAnnotations() // 启用数据注解验证 .ValidateOnStart(); // 启动时触发验证
通过以上方式,就能实现对集合内每个枚举元素的合法性校验。
内容的提问来源于stack exchange,提问作者pschill
相关产品推荐
相关产品推荐

