FluentValidation的循环引用导致Stack Overflow异常

时间:2018-01-30 22:05:50

标签: c# .net-core fluentvalidation

我需要验证可能具有循环引用的实体。 调用validate方法时,我得到一个stackOverflowException。

public class Person
{
    public string Name { get; set; }
    public Person Twin { get; set; }
}

public class PersonValidator : AbstractValidator<Person>
{
    public PersonValidator()
    {
        RuleFor(x => x.Name).NotEmpty();
        RuleFor(x => x.Twin).SetValidator(this);
    }
}

public static class Program
{
    public static void Main(string[] args)
    {
        var bob = new Person { Name = "bob" };
        var bill = new Person { Name = "bill" };
        bob.Twin = bill;
        bill.Twin = bob;
        var result = new PersonValidator().Validate(bob);
    }
}

如何打破循环引用?

谢谢,

2 个答案:

答案 0 :(得分:0)

这是预期的行为,有一种方法可以打破循环引用。但它需要比特编码练习。

  1. 首先将Twin上的RuleFor / SetValidator从验证器构造函数移动到Initialize方法。
  2. 将一个静态对象添加到PersonValidator并在其上调用initialize。然后在SetValidator上使用它。
  3. 以下是验证器的工作版本

    public class PersonValidator : AbstractValidator<Person>
    {
        public static readonly PersonValidator PersonValidator1 = new PersonValidator();
    
        static PersonValidator()
        {
            PersonValidator1.Initialize();
        }
    
        public PersonValidator()
        {
            RuleFor(x => x.Name).NotEmpty();
        }
        public void Initialize()
        {
            RuleFor(x => x.Twin).SetValidator(PersonValidator1);
        }
    }
    

答案 1 :(得分:0)

我发布的代码是实际代码的非常简化版本。

要求是验证实体包括对其所有可验证子实体的验证。 在创建验证器实例时,我使用反射来发现可验证的子实体并为它们创建规则: RuleFor(x => x.Twin).Custom((x, context) => ValidateChildEntity(x, context) 工作得很好,直到我遇到循环引用的情况。

我能够通过在Static对象中存储已经验证的实体列表来打破循环引用。我的ValidateChildEntity方法在调用Validator.Validate(x)之前检查了该列表。但这不是一个可以接受的解决方案。

我试图使用ValidationContext但没有成功。