namespace MS.Microservice.Core.Functional { /// /// Either 的核心组合能力。 /// public static partial class EitherExtensions { public static Task> AsTask(this Either either) => Task.FromResult(either); public static Task> RightAsync(R value) => Task.FromResult((Either)F.Right(value)); public static Task> LeftAsync(L value) => Task.FromResult((Either)F.Left(value)); public static Either Try(Func operation, string code = "unexpected") { try { return F.Right(operation()); } catch (Exception ex) { return F.Left(Error.FromException(ex, code)); } } public static Either Try(Action operation, string code = "unexpected") => Try(() => { operation(); return Unit.Default; }, code); public static async Task> TryAsync(Func> operation, string code = "unexpected") { try { return F.Right(await operation()); } catch (Exception ex) { return F.Left(Error.FromException(ex, code)); } } public static Task> TryAsync(Func operation, string code = "unexpected") => TryAsync(async () => { await operation(); return Unit.Default; }, code); public static async Task> Map(this Task> eitherTask, Func mapper) => (await eitherTask).Map(mapper); public static async Task> MapLeft(this Task> eitherTask, Func mapper) => (await eitherTask).MapLeft(mapper); public static async Task> Bind(this Task> eitherTask, Func> binder) => (await eitherTask).Bind(binder); public static async Task> BindAsync(this Task> eitherTask, Func>> binder) { var either = await eitherTask; return await either.BindAsync(binder); } public static async Task> MapAsync(this Task> eitherTask, Func> mapper) { var either = await eitherTask; return await either.MapAsync(mapper); } public static async Task> Tap(this Task> eitherTask, Action effect) => (await eitherTask).Tap(effect); public static async Task> TapAsync(this Task> eitherTask, Func effect) { var either = await eitherTask; return await either.TapAsync(effect); } public static async Task> Where(this Task> eitherTask, Func predicate, Func leftFactory) => (await eitherTask).Where(predicate, leftFactory); public static async Task MatchAsync(this Task> eitherTask, Func> left, Func> right) => await (await eitherTask).MatchAsync(left, right); public static async Task MatchAsync(this Task> eitherTask, Func left, Func right) => (await eitherTask).Match(left, right); extension(Either either) { public Either Map(Func left, Func right) => either.Match>( left: l => F.Left(left(l)), right: r => F.Right(right(r))); public Either Map(Func mapper) => either.Match>( left: l => F.Left(l), right: r => F.Right(mapper(r))); public Either MapLeft(Func mapper) => either.Match>( left: l => F.Left(mapper(l)), right: r => F.Right(r)); public Either Bind(Func> binder) => either.Match>( left: l => F.Left(l), right: binder); public Task> BindAsync(Func>> binder) => either.Match( left: l => Task.FromResult((Either)F.Left(l)), right: binder); public Task> MapAsync(Func> mapper) => either.Match>>( left: l => Task.FromResult((Either)F.Left(l)), right: async r => F.Right(await mapper(r))); public Either Tap(Action effect) { if (either.IsRight) { effect(either.Right); } return either; } public async Task> TapAsync(Func effect) { if (either.IsRight) { await effect(either.Right); } return either; } public R GetOrElse(R fallback) => either.Match( left: _ => fallback, right: r => r); public R GetOrElse(Func fallback) => either.Match( left: fallback, right: r => r); public Either OrElse(Either fallback) => either.Match( left: _ => fallback, right: _ => either); public Either Where(Func predicate, Func leftFactory) => either.Match>( left: l => F.Left(l), right: r => predicate(r) ? F.Right(r) : F.Left(leftFactory(r))); public Task MatchAsync(Func> left, Func> right) => either.Match(left, right); public Either Select(Func mapper) => either.Map(mapper); public Either SelectMany(Func> bind, Func project) => either.Bind(r => bind(r).Map(r2 => project(r, r2))); } } }