如何验证未知类型集合/可枚举对象?求模型属性校验方案
解决集合属性至少包含一个元素的验证问题
修复你的自定义验证Attribute
你遇到的核心问题是:非泛型的IEnumerable接口没有Any()扩展方法——LINQ的Any()是针对泛型IEnumerable<T>的扩展。不需要用反射,直接通过枚举器就能判断非泛型集合是否包含元素,修改后的验证逻辑如下:
public class CollectionHasAtLeastOneAttribute : ValidationAttribute { protected override ValidationResult IsValid(object? value, ValidationContext validationContext) { if (value == null) { return new ValidationResult("Collection object cannot be null."); } // 检查是否为集合类型 if (value is IEnumerable enumerable) { using var enumerator = enumerable.GetEnumerator(); // MoveNext()返回false说明集合没有元素 if (!enumerator.MoveNext()) { return new ValidationResult("Collection must have at least one record."); } } else { return new ValidationResult("The property is not a valid collection type."); } return ValidationResult.Success; } }
更优的集合验证方案
如果项目允许,推荐使用FluentValidation替代自定义Attribute,它的验证逻辑更清晰、扩展性更强,还能避免自定义Attribute的局限性:
- 首先安装FluentValidation包:
Install-Package FluentValidation # 或者用.NET CLI dotnet add package FluentValidation
- 为
MyModel编写验证器:
using FluentValidation; public class MyModelValidator : AbstractValidator<MyModel> { public MyModelValidator() { RuleFor(model => model.Items) .NotNull().WithMessage("Collection object cannot be null.") .Must(items => items.Any()).WithMessage("Collection must have at least one record."); } }
- 使用验证器:
var validator = new MyModelValidator(); var validationResult = validator.Validate(myModelInstance); if (!validationResult.IsValid) { // 处理验证错误 foreach (var error in validationResult.Errors) { Console.WriteLine(error.ErrorMessage); } }
如果坚持使用DataAnnotations体系,上面修复后的自定义Attribute已经能满足需求,无需额外反射操作——所有实现IEnumerable的集合类型(包括ICollection<T>、List<T>等)都能被正确验证。
内容的提问来源于stack exchange,提问作者M Kenyon II
相关产品推荐
相关产品推荐

