为Task扩展Linq

This commit is contained in:
Sanchime 2022-05-03 11:07:04 +08:00
parent bd9142b451
commit 040f6d9759
1 changed files with 92 additions and 1 deletions

View File

@ -1,4 +1,7 @@
using System.Collections.Generic;
using System;
using System.Threading.Tasks;
using Sanchime.Functional.Core.Products;
namespace Sanchime.Functional.Core.Extensions;
public static class TaskExtension
@ -9,7 +12,9 @@ public static class TaskExtension
#region
public static Task<R> Map<T, R>(this Task<T> @this, Func<Exception, R> Faulted, Func<T, R> Completed)
=> @this.ContinueWith(val => val.Status == TaskStatus.Faulted ? Faulted(val.Exception!) : Completed(val.Result));
=> @this.ContinueWith(val => val.Status == TaskStatus.Faulted
? Faulted(val.Exception!)
: Completed(val.Result));
public static async Task<R> Map<T, R>(this Task<T> @this, Func<T, R> mapping)
=> mapping(await @this.ConfigureAwait(false));
@ -22,16 +27,102 @@ public static class TaskExtension
public static Task<Func<T2, R>> Map<T1, T2, R>(this Task<T1> @this, Func<T1, T2, R> mapping)
=> @this.Map(mapping.Curry());
#endregion
#region
public static async Task<R> Bind<T, R>(this Task<T> @this, Func<T, Task<R>> binding)
=> await binding(await @this.ConfigureAwait(false)).ConfigureAwait(false);
#endregion
#region
public static async Task<R> Apply<T, R>(this Task<Func<T, R>> @this, Task<T> task)
=> (await @this.ConfigureAwait(false))(await task.ConfigureAwait(false));
public static Task<Func<T2, R>> Apply<T1, T2, R>(this Task<Func<T1, T2, R>> @this, Task<T1> task)
=> @this.Map(CurryingExtension.Curry).Apply(task);
#endregion
public static Task<T> OrElse<T>(this Task<T> @this, Func<Task<T>> fallback)
=> @this.ContinueWith(task => task.Status == TaskStatus.Faulted
? fallback()
: Task.FromResult(task.Result))
.Unwrap();
public static Task<T> Recover<T>(this Task<T> @this, Func<Exception, T> fallback)
=> @this.ContinueWith(task => task.Status == TaskStatus.Faulted
? fallback(task.Exception!)
: task.Result);
public static Task<T> RecoverWith<T>(this Task<T> @this, Func<Exception, Task<T>> fallback)
=> @this.ContinueWith(task => task.Status == TaskStatus.Faulted
? fallback(task.Exception!)
: Task.FromResult(task.Result))
.Unwrap();
public static Task<Unit> ForEach<T>(this Task<T> @this, Action<T> continuaction)
=> @this.ContinueWith(task => continuaction.ToFunc()(task.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
#region Linq式
public static async Task<RR> SelectMany<T, R, RR>(this Task<T> source, Func<T, Task<R>> binding, Func<T, R, RR> project)
{
var task = await source;
var result = await binding(task);
return project(task, result);
}
public static async Task<RR> SelectMany<T, R, RR>(this Task<T> source, Func<T, ValueTask<R>> binding, Func<T, R, RR> project)
{
var task = await source;
var result = await binding(task);
return project(task, result);
}
public static async Task<RR> SelectMany<T, R, RR>(this Task<T> source, Func<Unit, Task<R>> binding, Func<Unit, R, RR> project)
{
await source;
var result = await binding(Unit.Value);
return project(Unit.Value, result);
}
public static async Task<R> SelectMany<T, R, RR>(this Task<T> source, Func<T, Task<R>> binding)
=> await binding(await source.ConfigureAwait(false)).ConfigureAwait(false);
public static async Task<R> Select<T, R>(this Task<T> source, Func<T, R> mapping)
=> mapping(await source);
public static async Task<T> Where<T>(this Task<T> source, Func<T, bool> predicate)
{
var task = await source;
if (!predicate(task))
{
throw new OperationCanceledException();
}
return task;
}
public static async Task<V> Join<T, U, K, V>(this Task<T> source, Task<U> inner, Func<T, K> outerKeySelector, Func<U, K> innerKeySelector, Func<T, U, V> resultSelector)
{
await Task.WhenAll(source, inner);
if (!EqualityComparer<K>.Default.Equals(outerKeySelector(source.Result), innerKeySelector(inner.Result)))
{
throw new OperationCanceledException();
}
return resultSelector(source.Result, inner.Result);
}
public static async Task<V> GroupJoin<T, U, K, V>(this Task<T> source, Task<U> inner, Func<T, K> outerKeySelector, Func<U, K> innerKeySelector, Func<T, Task<U>, V> resultSelector)
{
var task = await source;
return resultSelector(task,
inner.Where(u => EqualityComparer<K>.Default.Equals(
outerKeySelector(task), innerKeySelector(u))));
}
#endregion
}