Asyn c / Ожидать Pattern. Как передать ожидаемый метод другому методу - PullRequest
3 голосов
/ 21 января 2020

В моем приложении мне нужно вызвать метод перед всем запросом API. Если определенное c условие выполнено, тогда мне нужно выполнить набор операторов в этом методе.

Чтобы обобщить это, я создал вспомогательный класс примерно так:

public class CertificateValidator {
readonly IDependencyService _serviceLocator;
public CertificateValidator(IDependencyService serviceLocator) {
    _serviceLocator = serviceLocator;
}

public async Task <T> TryExecuteWithCertificateValidationAsync <T> (Task <T> operation) {
    var service = _serviceLocator.Get <IDeviceService> ();
    if (service.CertificateValidationRequired()) {
        // My Code.
    }
    T actualResult = await operation;
    return actualResult;
}

}

И в моей модели представления я сделал что-то вроде этого.

 public CertificateValidator ValidateCertificate => new CertificateValidator(_serviceLocator);

var response = await ValidateCertificate
                            .TryExecuteWithCertificateValidationAsync(MyMethodAsync());

private async Task<RequestResult<Response>> MyMethodAsync()
{
     // Some code
}

Но когда я реализую таким образом, поток выполнения будет

  • Первый MyMethodAsyn Будет вызван c ().

  • И когда он достигает метода await, он выполняет метод TryExecuteWithCertificateValidationAsyn c и запускает оставшийся код там.

  • А потом, когда он достигает T actualResult = await operation; return actualResult;, управление go возвращается к MyMethodAsyn c () - жду заявления.

И мое сомнение здесь ,

Мне нужно полностью выполнить TryExecuteWithCertificateValidationAsyn c, а затем MyMethodAsyn c.

Короче говоря, как я говорил раньше Мне нужно выполнить набор кода, прежде чем я вызову все мои вызовы API. Как я могу добиться чего-то подобного, используя asyn c a a a await.

1 Ответ

2 голосов
/ 21 января 2020

Вместо передачи Task передать функцию:

public async Task<T> TryExecuteWithCertificateValidationAsync<T>(Func<Task<T>> operation)
{
    var service = _serviceLocator.Get<IDeviceService>();
    if (service.CertificateValidationRequired())
    {
        // My Code.
    }
    T actualResult = await operation();
    return actualResult;
}

var response = await ValidateCertificate
    .TryExecuteWithCertificateValidationAsync(MyMethodAsync);

Обновить согласно комментарию

Если метод требует аргументов, типы необходимо добавить в качестве дополнительных обобщенных c аргументов к Func:

private async Task<RequestResult<Response>> MyMethodAsync(int i)
{
     // Some code
}

public async Task<T> TryExecuteWithCertificateValidationAsync<T>(int, Func<Task<T>> operation) // Add int as second generic argument
{
    T actualResult = await operation(1); // Can now be called with an integer
    return actualResult;
}
...