I have the following async method
private async Task<bool> HasPolicy(AuthorizationFilterContext context, string policy)
{
var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
return authorized.Succeeded;
}
I would like to use it in Enumerable.All and Enumerable.Any extension
var result1 = IsAndPolicy
? policys.All(async x => await HasPolicy(context, x))
: policys.Any(async x => await HasPolicy(context, x));
But the above code gets the following error
Error CS4010 Cannot convert async lambda expression to delegate type 'Func<string, bool>'. An async lambda expression may return
void,TaskorTask<T>, none of which are convertible to 'Func<string, bool>'.
One approach would be to project to an IEnumerable<Task<bool>>
var results = await Task.WhenAll(policys.Select(x => HasPolicy(context, x)));
var result1 = IsAndPolicy
? results.All(x => x)
: results.Any(x => x);
The trouble with this approach, is you are processing all the items potentially needlessly.
Michael Randall's answer produces the correct logical result but has to evaluate all policies, even though in both cases the evaluation can be short-circuited, by the first false result for All, or the first true result for Any.
This can be avoided by converting the tasks to an IAsyncenumerable<T> and using 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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With