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

3
在我的应用程序中,我需要在所有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() - await语句。

我的疑问是:

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

简而言之,如我早先所说,我需要在调用所有API调用之前执行一组代码。 我如何使用async和await实现类似的功能。

1个回答

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;
}

@Sooraj,它肯定是可推断的;请参见此最小示例:https://dotnetfiddle.net/Rd5xZa - Johnathan Barclay
最后一个问题,如果我想将一些参数传递给MyMethodAsync(),我该如何更改呢?私有静态异步任务<RequestResult<Response>> MyMethodAsync(int i)。 - Sooraj
抱歉有这些愚蠢的疑问。因为我是新手,对这个环境不太熟悉。 - Sooraj
我认为它不能被视为通用解决方案@Sooraj,根据讨论,您需要在所有API调用之前执行此方法。假设如果您的不同API调用方法包含不同的参数,您如何将其概括?该解决方案仅适用于没有参数的方法。我认为最好的选择是使用Task.ContinueWith。但我不确定如何概括部分。 - StezPet
@Johnathan Barclay 我尝试执行您更新的答案,但并没有像您所解释的那样工作。 https://dotnetfiddle.net/xz65KU - StezPet
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接