1

我有以下三个实体,它们相互链接如下:

class Class1 
{ 
   int id { get; set; }
   Class2 { get; set; } 
}

class Class2 
{
   int id { get; set; }
   Class3 { get; set; } 
}

class Class3 
{ 
   int id { get; set; }
   Class1 { get; set; } 
}

现在我为这些类中的每一个创建了验证器,并且还SetValidator为链接到它们的实体创建了验证器:

//Class1 (and other classes) validator has following rules:
public class Class1Validator()
{
    public Class1Validator()
    {
        RuleFor(x => x.id).NotEqual(0).WithMessage("id is required.");
        RuleFor(x => x.Class2).SetValidator(new Class2Validator());
    }
}
public class Class2Validator()
{
    public Class2Validator()
    {
        RuleFor(x => x.id).NotEqual(0).WithMessage("id is required.");
        RuleFor(x => x.Class3).SetValidator(new Class3Validator());
    }
}
public class Class3Validator()
{
    public Class3Validator()
    {
        RuleFor(x => x.id).NotEqual(0).WithMessage("id is required.");
        RuleFor(x => x.Class1).SetValidator(new Class1Validator());
    }
}

//Now when following is called:
var validator = new Class1Validator();

当我检查 validate forClass1时,它还包含验证器 forClass2然后Class2有 for Class3,最后Class3还有验证器,Class1它形成一个无限循环并抛出以下错误:

mscorlib.dll 中出现“System.StackOverflowException”类型的未处理异常

并在查看完整详细信息时显示:

无法计算表达式,因为当前线程处于堆栈溢出状态。

对此有任何解决方案还是我在这里做错了什么?


更新:我还尝试了以下方法,如果对象为空,我可以限制验证器,但这不起作用:

When(x => x.Class1 != null, () => RuleFor(x => x.Class1).SetValidator(new Class1Validator()));
4

1 回答 1

0

我找到了一种打破循环引用的方法:

  • SetValidator调用从构造函数中移到Initialize()方法中。
  • SetValidator()调用重用验证器实例。例如,将验证器实例存储为静态类中的静态字段。

好吧,我不太会说话,所以这里是代码:

存放验证器实例并调用Initialize()它们的类:

public static class Validators
{
    public static Class1Validator Class1Validator = new Class1Validator();
    public static Class2Validator Class2Validator = new Class2Validator();
    public static Class3Validator Class3Validator = new Class3Validator();

    static Validators()
    {
        Class1Validator.Initialize();
        Class2Validator.Initialize();
        Class3Validator.Initialize();
    }
}

验证器现在变为:

public class Class1Validator : AbstractValidator<Class1>
{
    public Class1Validator()
    {
        RuleFor(x => x.id).NotEqual(0).WithMessage("id is required.");
    }
    public void Initialize()
    {
        RuleFor(x => x.Class2).SetValidator(Validators.Class2Validator);            
    }
}
public class Class2Validator : AbstractValidator<Class2>
{
    public Class2Validator()
    {
        RuleFor(x => x.id).NotEqual(0).WithMessage("id is required.");
    }
    public void Initialize()
    {
        RuleFor(x => x.Class3).SetValidator(Validators.Class3Validator);            
    }
}
public class Class3Validator : AbstractValidator<Class3>
{
    public Class3Validator()
    {
        RuleFor(x => x.id).NotEqual(0).WithMessage("id is required.");
    }
    public void Initialize()
    {
        RuleFor(x => x.Class1).SetValidator(Validators.Class1Validator);            
    }
}

我已经对此进行了测试,它似乎工作正常。例如:

var validator = Validators.Class1Validator;

var c1 = new Class1
    {
        id = 1,
        Class2 = new Class2
            {
                id = 2,
                Class3 = new Class3
                    {
                        id = 3,
                        Class1 = new Class1
                            {
                                id = 0,
                                Class2 = null
                            }
                    }
            }
    };

var result = validator.Validate(c1);

result这里是假的,因为内部Class1实例有一个Idof 0

我担心这种方法的线程安全,但显然没关系,如此所述:

验证器被设计为只被实例化一次——它们是线程安全的。

于 2013-09-15T20:11:01.317 回答