异步/等待模式。如何将等待方法传递给另一个方法

时间:2020-01-21 20:11:44

标签: c# async-await

在我的应用程序中,我需要在所有API请求之前调用一个方法。如果满足特定条件,则需要在该方法中执行一组语句。

为了概括这一点,我创建了一个类似这样的帮助器类。

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
}

但是当我这样实现时,执行流程是

  • 第一个MyMethodAsync()将被调用。

  • ,当它到达await方法时,它将执行 TryExecuteWithCertificateValidationAsync 方法并在其中运行其余代码。

  • 然后,当到达T actualResult = await operation; return actualResult;时,控件将返回MyMethodAsync()-等待语句。

我的疑问是,

我需要完全执行 TryExecuteWithCertificateValidationAsync ,然后执行 MyMethodAsync

简而言之,就像我之前说的那样,我需要在调用所有API调用之前执行一组代码。我如何使用异步等待来实现类似的目的。

1 个答案:

答案 0 :(得分:2)

不是传递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);

根据评论更新

如果该方法需要自变量,则类型必须作为Func的附加通用自变量的前缀:

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

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