C # utilise une expression lambda asynchrone avec une valeur booléenne de retour dans l'extension Enumerable.All

Sep 28 2020

J'ai la asyncméthode suivante

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

Je voudrais l'utiliser dans Enumerable.Allet l' Enumerable.Anyextension

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

Mais le code ci-dessus obtient l'erreur suivante

Erreur CS4010 Impossible de convertir l'expression lambda asynchrone en type de délégué «Func <string, bool>». Une expression lambda asynchrone peut renvoyer void, Task ou Task, dont aucun n'est convertible en 'Func <string, bool>'.

Réponses

4 00110001 Sep 28 2020 at 15:07

Une approche consisterait à projeter sur unIEnumerable<Task<bool>>

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

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

Le problème avec cette approche, c'est que vous traitez tous les éléments potentiellement inutilement.

2 PanagiotisKanavos Sep 28 2020 at 15:26

La réponse de Michael Randall produit le résultat logique correct mais doit évaluer toutes les politiques, même si dans les deux cas l'évaluation peut être court-circuitée, par le premier falserésultat pour Allou par le premier truerésultat pour Any.

Cela peut être évité en convertissant les tâches en IAsyncenumerable<T>et en utilisant 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));