From bcfe8c4c734c32d37a04b6cba2332095d6904350 Mon Sep 17 00:00:00 2001 From: Amichai Mantinband Date: Fri, 5 Jan 2024 15:50:18 +0200 Subject: [PATCH] Add Then/ThenAsync that invokes an action --- src/ErrorOr.cs | 34 +++++++++++++++++++++ src/ErrorOrExtensions.cs | 52 +++++++++++++++++++++++++-------- tests/ErrorOr.ThenAsyncTests.cs | 1 + tests/ErrorOr.ThenTests.cs | 26 +++++++++++++++-- 4 files changed, 98 insertions(+), 15 deletions(-) diff --git a/src/ErrorOr.cs b/src/ErrorOr.cs index 9f317eb..a5ee2d2 100644 --- a/src/ErrorOr.cs +++ b/src/ErrorOr.cs @@ -276,6 +276,23 @@ public ErrorOr Then(Func> onValue) return onValue(Value); } + /// + /// If the state is a value, the provided is invoked. + /// + /// The action to execute if the state is a value. + /// The original instance. + public ErrorOr Then(Action action) + { + if (IsError) + { + return Errors; + } + + action(Value); + + return this; + } + /// /// If the state is a value, the provided function is executed and its result is returned. /// @@ -308,6 +325,23 @@ public async Task> ThenAsync(Func + /// If the state is a value, the provided is invoked asynchronously. + /// + /// The action to execute if the state is a value. + /// The original instance. + public async Task> ThenAsync(Func action) + { + if (IsError) + { + return Errors; + } + + await action(Value).ConfigureAwait(false); + + return this; + } + /// /// If the state is a value, the provided function is executed asynchronously and its result is returned. /// diff --git a/src/ErrorOrExtensions.cs b/src/ErrorOrExtensions.cs index b4ef7d3..4d1de09 100644 --- a/src/ErrorOrExtensions.cs +++ b/src/ErrorOrExtensions.cs @@ -5,12 +5,12 @@ public static class ErrorOrExtensions /// /// If the state of is a value, the provided function is executed and its result is returned. /// - /// The type of the result. - /// The type of the next result. + /// The type of the result. + /// The type of the next result. /// The error. /// The function to execute if the state is a value. /// The result from calling if state is value; otherwise the original errors. - public static async Task> Then(this Task> errorOr, Func> onValue) + public static async Task> Then(this Task> errorOr, Func> onValue) { var result = await errorOr.ConfigureAwait(false); @@ -20,27 +20,41 @@ public static async Task> Then(this T /// /// If the state of is a value, the provided function is executed and its result is returned. /// - /// The type of the result. - /// The type of the next result. + /// The type of the result. + /// The type of the next result. /// The error. /// The function to execute if the state is a value. /// The result from calling if state is value; otherwise the original errors. - public static async Task> Then(this Task> errorOr, Func onValue) + public static async Task> Then(this Task> errorOr, Func onValue) { var result = await errorOr.ConfigureAwait(false); return result.Then(onValue); } + /// + /// If the state of is a value, the provided is invoked. + /// + /// The type of the result. + /// The error. + /// The action to execute if the state is a value. + /// The original . + public static async Task> Then(this Task> errorOr, Action action) + { + var result = await errorOr.ConfigureAwait(false); + + return result.Then(action); + } + /// /// If the state of is a value, the provided function is executed asynchronously and its result is returned. /// - /// The type of the result. - /// The type of the next result. + /// The type of the result. + /// The type of the next result. /// The error. /// The function to execute if the state is a value. /// The result from calling if state is value; otherwise the original errors. - public static async Task> ThenAsync(this Task> errorOr, Func>> onValue) + public static async Task> ThenAsync(this Task> errorOr, Func>> onValue) { var result = await errorOr.ConfigureAwait(false); @@ -50,18 +64,32 @@ public static async Task> ThenAsync(t /// /// If the state of is a value, the provided function is executed asynchronously and its result is returned. /// - /// The type of the result. - /// The type of the next result. + /// The type of the result. + /// The type of the next result. /// The error. /// The function to execute if the state is a value. /// The result from calling if state is value; otherwise the original errors. - public static async Task> ThenAsync(this Task> errorOr, Func> onValue) + public static async Task> ThenAsync(this Task> errorOr, Func> onValue) { var result = await errorOr.ConfigureAwait(false); return await result.ThenAsync(onValue).ConfigureAwait(false); } + /// + /// If the state of is a value, the provided is executed asynchronously. + /// + /// The type of the result. + /// The error. + /// The action to execute if the state is a value. + /// The original . + public static async Task> ThenAsync(this Task> errorOr, Func action) + { + var result = await errorOr.ConfigureAwait(false); + + return await result.ThenAsync(action).ConfigureAwait(false); + } + /// /// If the state is error, the provided function is executed asynchronously and its result is returned. /// diff --git a/tests/ErrorOr.ThenAsyncTests.cs b/tests/ErrorOr.ThenAsyncTests.cs index 5becc0e..10d9541 100644 --- a/tests/ErrorOr.ThenAsyncTests.cs +++ b/tests/ErrorOr.ThenAsyncTests.cs @@ -32,6 +32,7 @@ public async Task CallingThenAsync_WhenIsError_ShouldReturnErrors() ErrorOr result = await errorOrString .ThenAsync(str => ConvertToIntAsync(str)) .ThenAsync(num => Task.FromResult(num * 2)) + .ThenAsync(num => Task.Run(() => { _ = 5; })) .ThenAsync(num => ConvertToStringAsync(num)); // Assert diff --git a/tests/ErrorOr.ThenTests.cs b/tests/ErrorOr.ThenTests.cs index 0f373a7..5b8325f 100644 --- a/tests/ErrorOr.ThenTests.cs +++ b/tests/ErrorOr.ThenTests.cs @@ -22,6 +22,23 @@ public void CallingThen_WhenIsSuccess_ShouldInvokeGivenFunc() result.Value.Should().BeEquivalentTo("10"); } + [Fact] + public void CallingThen_WhenIsSuccess_ShouldInvokeGivenAction() + { + // Arrange + ErrorOr errorOrString = "5"; + + // Act + ErrorOr result = errorOrString + .Then(str => { _ = 5; }) + .Then(str => ConvertToInt(str)) + .Then(str => { _ = 5; }); + + // Assert + result.IsError.Should().BeFalse(); + result.Value.Should().Be(5); + } + [Fact] public void CallingThen_WhenIsError_ShouldReturnErrors() { @@ -32,6 +49,7 @@ public void CallingThen_WhenIsError_ShouldReturnErrors() ErrorOr result = errorOrString .Then(str => ConvertToInt(str)) .Then(num => num * 2) + .Then(str => { _ = 5; }) .Then(num => ConvertToString(num)); // Assert @@ -46,15 +64,17 @@ public async Task CallingThenAfterThenAsync_WhenIsSuccess_ShouldInvokeGivenFunc( ErrorOr errorOrString = "5"; // Act - ErrorOr result = await errorOrString + ErrorOr result = await errorOrString .ThenAsync(str => ConvertToIntAsync(str)) .Then(num => num * 2) .ThenAsync(num => ConvertToStringAsync(num)) - .Then(str => ConvertToInt(str)); + .Then(str => ConvertToInt(str)) + .ThenAsync(num => ConvertToStringAsync(num)) + .Then(num => { _ = 5; }); // Assert result.IsError.Should().BeFalse(); - result.Value.Should().Be(10); + result.Value.Should().Be("10"); } [Fact]