#c# #fluentvalidation
#c# #fluentvalidation
Вопрос:
Я использую FluentValidation для проверки сервера, и в одной из проверок используется пользовательский метод расширения с параметром. Указанный метод потребует еще нескольких параметров от корневого объекта (сущности).
В настоящее время код:
RuleFor(entity => entity.A).CustomExtension("test")
...
public static IRuleBuilder<T, string> CustomExtension<T>(this IRuleBuilder<T, string> builder, string someValue){
Мне нужно изменить это так, чтобы…
RuleFor(entity => entity.A).CustomExtension(entity.PropertyB) //<- basically need to pass a entity property as variable
public static IRuleBuilder<T, string> CustomExtension<T>(this IRuleBuilder<T, string> builder, string propertyA){
}
Очень признателен за любую помощь!
Ответ №1:
У вас нет доступа к экземпляру для проверки во время построения средства проверки. Вероятно, есть несколько способов сделать это, которые могут зависеть от того, какой тип правила вы пытаетесь реализовать.
Я имею в виду два способа использования существующих пользовательских валидаторов, которые предоставляют экземпляр для проверки (напрямую или через контекст). Первый дает вам только это, экземпляр, переданный в средство проверки, последний дополнительно предоставляет вам контекст, который вы можете использовать для предоставления данных в средство проверки во время выполнения.
Давайте предположим, что вы можете использовать расширение Must для создания своего пользовательского средства проверки, что означает, что мы рассматриваем первый случай. Должен иметь несколько перегрузок, одна из которых обеспечивает проверку экземпляра как части функции lambda. Следующий пример LINQPad показывает, как вы можете использовать это для создания собственного расширения:
void Main()
{
var validator = new MyValidator();
var myEntity1 = new MyEntity();
myEntity1.A = Guid.NewGuid();
myEntity1.B = myEntity1.A;
var validateResult1 = validator.Validate(myEntity1);
Console.WriteLine("Expected result: no errors");
Console.WriteLine(validateResult1.Errors.Select(x => x.ErrorMessage));
var myEntity2 = new MyEntity();
myEntity2.A = Guid.NewGuid();
myEntity2.B = Guid.NewGuid();
var validateResult2 = validator.Validate(myEntity2);
Console.WriteLine("Expected result: 3 errors");
Console.WriteLine(validateResult2.Errors.Select(x => x.ErrorMessage));
}
public class MyEntity
{
public Guid A { get; set; }
public Guid B { get; set; }
}
public class MyValidator : AbstractValidator<MyEntity>
{
public MyValidator()
{
RuleFor(x => x.A).Equal(x => x.B).WithMessage("Error via equal");
RuleFor(x => x.A).Must((myEntityInstance, valueOfA) => myEntityInstance.B.Equals(valueOfA)).WithMessage("Error via normal must");
RuleFor(x => x.A).CustomExtension(x => x.B).WithMessage("Error via custom extension");
}
}
public static class Extensions
{
public static IRuleBuilderOptions<T, TProperty> CustomExtension<T, TProperty, TCompareTo>
(this IRuleBuilder<T, TProperty> ruleBuilder, Func<T, TCompareTo> propertyToCompareTo)
{
return ruleBuilder.Must((myEntityInstance, valueOfA) => propertyToCompareTo(myEntityInstance).Equals(valueOfA));
}
}
Результат:
Это немного надуманно из-за отсутствия знания того, что будет делать ваше пользовательское расширение, но оно демонстрирует один из способов получения экземпляра для проверки во время выполнения в вашем собственном расширении.