2016-04-03 161 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)。這是允許您訪問這兩個屬性的技巧。