2016-04-03 65 views
3

我有这2类:将儿童财产与父母财产进行比较?

public class Master 
{ 
    public int? TotalAmount; 
    public ICollection<Detail> Details; 
} 

public class Detail 
{ 
    public int Amount; 
} 

我试图创建一个规则,使信息采集的总量等于主的总量财产。

我想下面的规则,但我不能访问主的财产:

RuleFor(x => x.Details) 
    .Must(coll => coll.Sum(item => item.Amount) == x.TotalAmount) 
    .When(x => x.Details != null) 
    .When(x => x.TotalAmount.HasValue); 

什么是实现这种规则的正确方法是什么?

+1

作为一个侧面说明。为什么要验证可以简单计算的东西?这种验证无论如何都需要计算,但整个事情变得更加复杂。 –

+0

@DiligentKeyPresser类和属性名称就是为了这个问题的例子。 –

+0

无论哪种方式,他所做的一点是,您造成的情况是您必须强制执行两个表数据之间的同步,基本上复制了否则可能只存在于详细对象中的功能,而与您使用的具体示例无关。 – Bon

回答

1

你可以只使用必须的另一超载,像这样:

RuleFor(x => x.Details) 
    .Must((master, details, ctx) => master.TotalAmount == details.Sum(r => r.Amount))    
    .When(x => x.Details != null) 
    .When(x => x.TotalAmount.HasValue); 

然而值得注意的是,在评论已经指出的,你不应该使用验证一致性检查。你只有一段数据(细节总数)。那么,为什么不这样做呢:

public class Master { 
    public int? TotalAmount 
    { 
     get 
     { 
      if (Details == null) 
       return null; 
      return Details.Sum(c => c.Amount); 
     } 
    } 

    public ICollection<Detail> Details; 
} 
+0

我知道我可以做到这一点,而且我打算这样做,但是我不想将这样的属性添加到模型类中,以避免在POCO类中添加这样的逻辑。 –

+0

我不能想象很多情况下这样做是合理的,但无论如何,你比我更了解你的情况。 – Evk

0

我已经发现,实现这种类型的验证,最好的方法是使用诸如自定义验证方法如下:

public class Validator : AbstractValidator<Master> 
{ 
    public Validator() 
    { 
     RuleFor(master => master) 
      .Must(CalculateSumCorrectly) 
      .When(master => master.Details != null) 
      .When(master => master.TotalAmount.HasValue); 
    } 

    private bool CalculateSumCorrectly(Master arg) 
    { 
     return arg.TotalAmount == arg.Details.Sum(detail => detail.Amount); 
    } 
} 

注意,此处被描述为应用到整个主对象的规则; RuleFor(master => master)。这是允许您访问这两个属性的技巧。