Как настроить пользовательский валидатор для свойства, возвращающего задачу, с помощью Fluent Validator

#c# #asp.net-core #.net-core #async-await #fluentvalidation

Вопрос:

Я пытаюсь установить пользовательский валидатор для свойства, которое асинхронно возвращает список объектов

 public Task<IList<ComplexType>> Property { get; set; }
 

Есть ли другой способ, кроме как установить его, не вызывая .Result администрацию?

 RuleForEach(x => x.Property.Result).SetValidator(new MyComplexValidator());
 

Комментарии:

1. Свойства не должны быть асинхронными: blog.stephencleary.com/2013/01/async-oop-3-properties.html

2. @JohnathanBarclay В моем случае свойство возвращает значение, которое дорого создать, поэтому его следует кэшировать для использования в будущем. Асинхронная операция выполняется только один раз: при первом запросе. После завершения операции результат операции будет кэширован и немедленно возвращен

Ответ №1:

Я полностью согласен с комментарием @Johnathan, свойства не должны быть асинхронными, и я настоятельно рекомендую вам пересмотреть свой дизайн.

Но, чтобы ответить на ваш вопрос, на самом деле нет никакого способа вызвать RuleForEach() для задачи, потому что для этого требуется перечисление, а задача<IList> не является перечисляемой. В качестве обходного пути вы можете использовать MustAsync() для запуска задачи, а затем использовать другой валидатор для проверки вашего сложного типа. Проверьте пример ниже.

 public class ComplexType
{
}

public class SomeType
{
    public Task<IList<ComplexType>> Property { get; set; }
}

public class ComplexTypeValidator : AbstractValidator<ComplexType>
{
    public ComplexTypeValidator()
    {
        //Your Validation Logic Here
    }
}

public class SomeTypeValidator : AbstractValidator<SomeType>
{
    public SomeTypeValidator(IValidator<ComplexType> complexTypeValidator)
    {
        RuleFor(o => o.Property)
            .MustAsync(async (property, cancellationToken) =>
            {
                var propertyResult = await property;
                return propertyResult.Aggregate(true, (result, o) => result amp;amp; complexTypeValidator.Validate(o).IsValid);
            });
    }
}
 

В этом примере я использовал MustAsync() для асинхронного запуска свойства и использовал другой валидатор для complexType. К сожалению, вы также не можете использовать RuleForEach() в MustAsync, поэтому вам придется самостоятельно просматривать список, как в примере.