gpt4 book ai didi

c# - FluentValidation 递归列表导致栈溢出

转载 作者:行者123 更新时间:2023-12-05 05:11:08 28 4
gpt4 key购买 nike

我正在使用 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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com