C # usa un'espressione lambda asincrona con return bool nell'estensione Enumerable.All

Sep 28 2020

Ho il seguente asyncmetodo

private async Task<bool> HasPolicy(AuthorizationFilterContext context, string policy)
{
    var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
    return authorized.Succeeded;
}

Vorrei usarlo in Enumerable.Alle Enumerable.Anyextension

var result1 = IsAndPolicy
    ? policys.All(async x => await HasPolicy(context, x))
    : policys.Any(async x => await HasPolicy(context, x));

Ma il codice precedente ottiene il seguente errore

Errore CS4010 Impossibile convertire l'espressione lambda asincrona nel tipo delegato "Func <string, bool>". Un'espressione lambda asincrona può restituire void, Task o Task, nessuno dei quali è convertibile in "Func <string, bool>".

Risposte

4 00110001 Sep 28 2020 at 15:07

Un approccio potrebbe essere quello di proiettare su un fileIEnumerable<Task<bool>>

var results = await Task.WhenAll(policys.Select(x => HasPolicy(context, x)));

var result1 = IsAndPolicy 
   ? results.All(x => x)                
   : results.Any(x => x);

Il problema con questo approccio è che stai elaborando tutti gli elementi potenzialmente inutilmente.

2 PanagiotisKanavos Sep 28 2020 at 15:26

La risposta di Michael Randall produce il risultato logico corretto ma deve valutare tutte le politiche, anche se in entrambi i casi la valutazione può essere cortocircuitata, dal primo falserisultato per All, o dal primo truerisultato per Any.

Questo può essere evitato convertendo le attività in un IAsyncenumerable<T>e utilizzando System.Linq.Async :

var resultTasks=policies.ToAsyncEnumerable()
                        .Select(async x => await HasPolicy(context, x));

var result1 = await (IsAndPolicy 
                       ? resultTasks.AllAsync(x => x)                
                       : resultTasks.AnyAsync(x => x));