- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 FluentValidation.AspNetcore 8.2.2,并且有一个对象模型,其中包含相同类型的子项列表。我想使用流畅的验证来验证对象。尝试为子对象设置验证器时,我遇到堆栈溢出异常和/或集合已更改(典型的 foreach 循环问题)。
为了测试和找到解决方案,我设置了一个带有单元测试的简单 .net 核心类库项目。
基础模型
using FluentValidation;
public class BaseModelItem
{
public int ItemId { get; set; }
public string Name { get; set; }
private List<BaseModelItem> ChildItems { get; set; }
}
public class BaseModelItemValidator : AbstractValidator<BaseModelItem>
{
public BaseModelItemValidator()
{
RuleFor(i => i.ItemId).GreaterThanOrEqualTo(0).WithMessage("Item id may not be negative.");
RuleFor(i => i.Name).NotNull().NotEmpty().WithMessage("Item name cannot be empty.");
RuleFor(i => i.ChildItems).ForEach(i => i.SetValidator(new BaseModelItemValidator()));
}
}
单元测试
public class Tests
{
[Test]
public void Test_Name_Cannot_Null()
{
var item = new BaseModelItem
{
ItemId = 2,
Name = null,
ChildItems = new List<BaseModelItem>()
};
var validator = new BaseModelItemValidator();
validator.ShouldHaveValidationErrorFor(t => t.Name, item);
Assert.Pass();
}
}
这个测试会导致堆栈溢出异常。我尝试过使用支持字段、初始化甚至更改为数组。我可以使用自定义验证器成功地否定 stackover 流异常。
public class BaseModelItemValidator : AbstractValidator<BaseModelItem>
{
public BaseModelItemValidator()
{
RuleFor(i => i.ItemId).GreaterThanOrEqualTo(0).WithMessage("Item id may not be negative.");
RuleFor(i => i.Name).NotNull().NotEmpty().WithMessage("Item name cannot be empty.");
RuleFor(i => i.ChildItems).Must(BeValidChildItemList);
}
private bool BeValidChildItemList(List<BaseModelItem> list)
{
if (list.Count > 0)
{
RuleFor(i => i.ChildItems).ForEach(i => i.SetValidator(new BaseModelItemValidator()));
}
return true;
}
}
允许它验证没有子项的对象。但是,如果您使用已填充的子对象运行测试,我会收到错误消息“集合已修改;枚举操作可能无法执行”。堆栈跟踪
StackTrace:
at System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()
at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
at FluentValidation.AbstractValidator`1.Validate(ValidationContext`1 context) in ****\FluentValidation\src\FluentValidation\AbstractValidator.cs:line 115
at FluentValidation.DefaultValidatorExtensions.Validate[T](IValidator`1 validator, T instance, IValidatorSelector selector, String ruleSet) in ******\FluentValidation\src\FluentValidation\DefaultValidatorExtensions.cs:line 876
at FluentValidation.TestHelper.ValidationTestExtension.TestValidate[T,TValue](IValidator`1 validator, Expression`1 expression, T instanceToValidate, TValue value, String ruleSet, Boolean setProperty) in ******\FluentValidation\src\FluentValidation\TestHelper\ValidatorTestExtensions.cs:line 101
at FluentValidation.TestHelper.ValidationTestExtension.ShouldHaveValidationErrorFor[T,TValue](IValidator`1 validator, Expression`1 expression, T objectToTest, String ruleSet) in *******\FluentValidation\src\FluentValidation\TestHelper\ValidatorTestExtensions.cs:line 40
at Tests.Tests.Test_Name_Cannot_Null_Nested() in \FluentValidationChildern\FluentValidationChildern.Tests\UnitTest1.cs:line 55
我无法找到可行的解决方案。
最佳答案
虽然我无法使用 SetValidator 方法使 Fluent 正常工作,但我确实有一个可行的解决方法并且可以改进。
在我设置的子列表上使用'Must'方法,然后实现一个手动函数来循环子项并手动构造验证器对象并检查结果。
public class BaseModelItemValidator : AbstractValidator<BaseModelItem>
{
public BaseModelItemValidator()
{
RuleFor(i => i.ItemId).GreaterThanOrEqualTo(0).WithMessage("Item id may not be negative.");
RuleFor(i => i.Name).NotNull().NotEmpty().WithMessage("Item name cannot be empty.");
RuleFor(i => i.ChildItems).Must(BeValidChildItemList);
}
private bool BeValidChildItemList(List<BaseModelItem> list)
{
if (list == null || list.Count == 0) return true;
foreach (var child in list)
{
var validator = new BaseModelItemValidator();
var validatorResults = validator.Validate(child);
if (!validatorResults.IsValid)
{
return false;
}
}
return true;
}
}
关于c# - FluentValidation 递归列表导致栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55804470/
如果另一个属性“Found”为真,我正在尝试使用 FluentValidation 来验证属性“Username”。 Object Contains: string Username bo
如果另一个属性“Found”为真,我正在尝试使用 FluentValidation 来验证属性“Username”。 Object Contains: string Username bo
我有一个包含需要验证的集合的类。集合上的泛型采用接口(interface),可以将不同的类型添加到集合中。 创建支持多态性的 FluentValidation 验证器的最简洁路径是什么? public
我已经开始使用 FluentValidation在 WPF 项目中,到目前为止,我以一种简单的方式使用它,检查字段是否已填充或少于 n 个字符。 现在我必须检查插入的值(这是一个字符串......该死
如何使用流畅的验证来验证整数列表? 我的模型有: public List WindowGlassItems { get; set; } 模型验证器有 RuleFor(x => x.WindowGla
如何使用流畅的验证来验证整数列表? 我的模型有: public List WindowGlassItems { get; set; } 模型验证器有 RuleFor(x => x.WindowGla
我在不止一个程序集中有 FluentValidators。在 FluentValidation 的早期版本中,我可以这样注册: services.AddMvc() .AddFluentValida
试图找出让 NHibernate ISession 成为流畅的验证抽象验证器的最佳方法。问题是 ISession 是根据 Web 请求注册的,而验证器出于性能原因根据 fluent 的最佳实践注册为单
我已经尝试在我的 ASP.NET MVC4 项目中设置 Ninject.Web.Mvc.FluentValidation如下图: var ninjectValidatorFactory = new N
我正在使用 FluentValidation.AspNetcore 8.2.2,并且有一个对象模型,其中包含相同类型的子项列表。我想使用流畅的验证来验证对象。尝试为子对象设置验证器时,我遇到堆栈溢出异
我想试试 .NET FluentValidation用于即将进行的项目的表单输入验证的库。在查看文档时,我发现了这个: 性能说明 由于 RuleFor 定义中的表达式树编译和解析,验证器的实例化是一个
我只想验证在我的模型上发生更改的属性,不幸的是,默认情况下流畅的验证似乎会验证调用 Validator.Validate(instanceToValidate) 时具有规则的每个属性 我已经尝试将 P
我有课: Sponsored { int Order }; 我收集了它: IEnumerable sponsored; 我想检查 Order 对于这个集合是否是唯一的。 我可以通过 FluentVal
我正在使用图书馆 "FluentValidation.AspNetCore": "6.4.0-beta3"在 .netcore WebApi在一个项目中。您可以在下面看到项目结构。如果我放置 Curr
Reading the documentation在 .NET Core 中,您似乎可以使用以下方法进行隐式子属性验证: services.AddMvc().AddFluentValidation(f
我有这个验证器: public class InputValidator : AbstractValidator { public InputValidator() {
我正在 .NET Core 中使用 FluentValidator。大多数情况下,一切都运行良好,但我注意到在处理复杂类型时,FluentValidator 会显示完整的属性名称。例如,假设我有一个名
我正在努力为一个类实现一个验证器,其中应该只设置一个属性。 假设我们有以下类: public class SomeClass { public DateTime SomeDate {get;
我一直在 ASP.NET MVC 3 中的 View 模型上使用 FluentValidation,它工作得很棒! 我现在想将它用作我的服务层内域对象的验证引擎。 你能用它做复杂的验证方案吗? 我正在
我想像这样使用 FluentValidation: public class CustomValidator : AbstractValidator { public CustomValidato
我是一名优秀的程序员,十分优秀!