Если вам необходимо применить правило проверки для сбора имущества, но по-прежнему необходимо иметь доступ к основной модели и (или) всей коллекции, а не только пункт проверяемого, то RuleForEach
метод ваш выбор:
var comparer = new SubEntityComparer();
RuleForEach(x => x.SubEntities)
.Must((model, submodel) => model.SubEntities.Count(xsub => comparer.Equals(xsub, submodel)) == 1) // one match that ReferenceEquals hit
.WithMessage("The item with values {0}, {1} has duplicates in collection of {2} items",
(model, submodel) => submodel.Field1,
(model, submodel) => submodel.Field2,
(model, submodel) => model.SubEntities.Count); // in validation message generation you can access to current item as well as to main model
Если вы нужно только одно сообщение об ошибке для правила проверки, которую вы описали - вы можете применить простое правило предиката для сбора имущества SubEntites
:
RuleFor(x => x.SubEntities)
.Must(coll => coll.Distinct(new SubEntityComparer()).Count() == coll.Count)
.WithMessage("One or more items in collection of {0} items are duplicates",
(model, coll) => coll.Count); // has access to collection and to main model
в обоих случаях я использовал тот же компаратор равенство, но вы можете переопределить Equals
, а также использовать перегрузки IEnumerable
методов расширения с перегрузкой, которые исключают параметр EqualityComparer
.
Кодекс EqualityComparer перечислены ниже:
public class SubEntityComparer : IEqualityComparer<SubEntity>
{
public bool Equals(SubEntity x, SubEntity y)
{
if (x == null^y == null)
return false;
if (ReferenceEquals(x, y))
return true;
// your equality comparison logic goes here:
return x.Field1 == y.Field1 &&
x.Field2 == y.Field2;
}
public int GetHashCode(SubEntity obj)
{
return obj.Field1.GetHashCode() + 37 * obj.Field2.GetHashCode();
}
}
Update:
В обоих способах осуществления проверки для сбора вы можете использовать SetCollectionValidator(new SubEntityValidator())
для проверки каждого элемента с помощью простых правил самостоятельно.
Вам не нужно утилизировать SubEntityComparer? – polonskyg
IEqualityComparer реализация stateless (без полей), более того, он участвует в закрытии - метод проверки будет выполнен после завершения определения кода определения. –
Почему вы решили реализовать компаратор, а не просто это: '.Must ((model, subodel) => model.SubEntities.Count (xsub => xsub.Field1 == submodel.Field1 && xsub.Field2 == subodel.Field2)) == 1) '? – Mir