У меня есть приложение для составления бюджета, которое позволяет бюджетам иметь суб-бюджеты N-уровня.Рассматриваемый класс: LineItem
:
class LineItem
{
public string Name { get; set; }
public Guid Id{ get; set; }
public ICollection<LineItem> Children = new HashSet<LineItem>();
public virtual IDictionary<string, double> Budgets {get; set;}
}
Я пытаюсь создать Fluid Validator для этого класса с учетом следующих правил:
- Это N-Уровень ... Мне нужно иметь возможность проверять на каждом уровне.
- Мне нужно знать, на каком уровне (по идентификатору?) Проверка не удалась.
- Проверки должны ускориться.
- Нулевой бюджет означает неограниченный ... Это усложняет ситуацию.
Итак, для действительного / сложного примера бюджета:
validParent (food budget=100)
├── child1 (unlimited food budget)
│ ├── grandchild1 (food budget=15)
│ ├── grandchild2 (food budget=10)
└── child2 (food budget=75)
и вот то же самоенедопустимая структура:
validParent (food budget=100)
├── child1 (unlimited food budget)
│ ├── grandchild1 (food budget=15)
│ ├── grandchild2 (food budget=70) <- sum of the children on this branch is too much!
└── child2 (food budget=75) <- not enough left!
У меня есть валидатор, который работает на любом уровне с дочерним, но только с прямым дочерним:
public class BudgetValidator : AbstractValidator<LineItem>
{
public BudgetValidator()
{
RuleFor(evtNode => evtNode.Budgets).Custom((budgets, context) =>
{
LineItem parent = context.InstanceToValidate as LineItem;
if (parent.Budgets != null) // check if this level is null. if it is, it is valid.
{
IDictionary<string, double> childBudgets = parent.Children.SelectMany(d => d.Budgets).GroupBy(
dict => dict.Key,
dict =>
{
if (parent.Budgets.ContainsKey(dict.Key) && parent.Budgets[dict.Key] < dict.Value)
{
context.AddFailure($"Invalid child budget ({dict.Key}). Child budget must not exceed that of parent.");
}
return dict.Value;
},
(key, g) => new { Key = key, Value = g.Sum() }
).ToDictionary(e => e.Key, e => e.Value);
foreach (var budget in childBudgets)
{
if (parent.Budgets.ContainsKey(budget.Key))
{
if (parent.Budgets[budget.Key] < budget.Value)
{
context.AddFailure($"Invalid budget. Sum of Budgets ({budget.Key}) must not exceed that of parent.");
}
}
}
}
});
RuleForEach(evtNode => evtNode.Children).SetValidator(this);
}
Как я могу объяснитькогда уровень имеет «неограниченный бюджет»? Это дети будут рассматривать его как «неограниченный», но родитель должен знать, если внуки превысили лимит.
Вот скрипка дотнет с классомhttps://dotnetfiddle.net/Nkc4ob