Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ make All method async

Hello i'm looking for a way to make All method run in async mode. As a matter of fact i'm trying to figure a way on how to make use of async whenever i need it in LINQ. Some linq methods have also async definition and i don't quite understand why not all methods have async definition, so maybe someone can clear things up for me.

Related to me trying to make All run async

Version 1

 async Task<bool> IHrtbProfileValidator.ValidateHrtb(UserHrtbProfileDTO dto_Hrtb)
        {
            var x = _validator.All(async (ck) => await ck.ValidateHrtb(dto_Hrtb));
            return x;
        }

Version 2

var x = _validator.All((ck) => await ck.ValidateHrtb(dto_Hrtb));

Version 3

  var x = _validator.All(async (ck) => await ck.ValidateHrtb(dto_Hrtb).Result);

this is what i've tried

The idea is that i have a IValidator interface from which multiple validator classes implement each responsible with its own validation related logic . In the MainValidator class i'm just looking to call All method to validate a list of IValidator.

Thank you all

like image 806
Remus Avatar asked Sep 20 '16 14:09

Remus


1 Answers

You can not make the All method itself async, but what you can do is do a Select, await the result, then pass that result to All

async Task<bool> IHrtbProfileValidator.ValidateHrtb(UserHrtbProfileDTO dto_Hrtb)
{
    IEnumerable<Task<bool>> items = _validator.Select(ck => ck.ValidateHrtb(dto_Hrtb));
    bool[] results = await Task.WhenAll(items);
    var x = results.All(item => item);
    return x;
}

Another option is you can make your own AllAsync extension method that works with with tasks as sources or predicates.

public static class ExtensionMethods
{
    // This is for async predicates with either a sync or async source.
    // This is the only one you need for your example
    public static async Task<bool> AllAsync<TSource>(this IEnumerable<TSource> source, Func<TSource, Task<bool>> predicate)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
        if (predicate == null)
            throw new ArgumentNullException(nameof(predicate));
        foreach (var item in source)
        {
            var result = await predicate(item);
            if (!result)
                return false;
        }
        return true;
    }

    // This is for synchronous predicates with an async source.
    public static async Task<bool> AllAsync<TSource>(this IEnumerable<Task<TSource>> source, Func<TSource, bool> predicate)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
        if (predicate == null)
            throw new ArgumentNullException(nameof(predicate));
        foreach (var item in source)
        {
            var awaitedItem = await item;
            if (!predicate(awaitedItem))
                return false;
        }
        return true;
    }
}

You could then do

async Task<bool> IHrtbProfileValidator.ValidateHrtb(UserHrtbProfileDTO dto_Hrtb)
{
    var x = await _validator.AllAsync((ck) => ck.ValidateHrtb(dto_Hrtb));
    return x;
}
like image 56
Scott Chamberlain Avatar answered Oct 30 '22 06:10

Scott Chamberlain