-
Notifications
You must be signed in to change notification settings - Fork 300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Features/combine sequential #280
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
using FluentAssertions; | ||
|
||
using Xunit; | ||
|
||
using static CSharpFunctionalExtensions.Tests.ResultTests.CombineWithErrorMethodTests; | ||
|
||
namespace CSharpFunctionalExtensions.Tests.ResultTests | ||
{ | ||
public class CombineSequentialMethodTests | ||
{ | ||
[Fact] | ||
public async Task CombineSequential_execute_all_functions_when_all_are_success() | ||
{ | ||
var firstReturnValue = 12; | ||
var secondReturnValue = "value"; | ||
Task<Result<int>> FirstFunction() => Task.FromResult(Result.Success(firstReturnValue)); | ||
|
||
Task<Result<string>> SecondFunction() => Task.FromResult(Result.Success(secondReturnValue)); | ||
|
||
var result = await Result.CombineSequential(FirstFunction, | ||
SecondFunction, | ||
values => new | ||
{ | ||
values.DataA, | ||
values.DataB | ||
}); | ||
|
||
result.IsSuccess.Should().BeTrue(); | ||
result.Value.DataA.Should().Be(firstReturnValue); | ||
result.Value.DataB.Should().Be(secondReturnValue); | ||
} | ||
[Fact] | ||
public async Task CombineSequential_execute_first_functions_when_it_fails() | ||
{ | ||
var errorValue = "First function error"; | ||
Task<Result<int>> FirstFunction() => Task.FromResult(Result.Failure<int>(errorValue)); | ||
|
||
Task<Result<string>> SecondFunction() => Task.FromResult(Result.Success("value")); | ||
|
||
var result = await Result.CombineSequential(FirstFunction, | ||
SecondFunction, | ||
values => new | ||
{ | ||
values.DataA, | ||
values.DataB | ||
}); | ||
result.IsSuccess.Should().BeFalse(); | ||
result.Error.Should().Be(errorValue); | ||
} | ||
[Fact] | ||
public async Task CombineSequential_execute_all_functions_when_second_fails() | ||
{ | ||
var errorValue = "Second function error"; | ||
|
||
Task<Result<string>> FirstFunction() => Task.FromResult(Result.Success("value")); | ||
|
||
|
||
Task<Result<int>> SecondFunction() => Task.FromResult(Result.Failure<int>(errorValue)); | ||
|
||
|
||
var result = await Result.CombineSequential(FirstFunction, | ||
SecondFunction, | ||
values => new | ||
{ | ||
values.DataA, | ||
values.DataB | ||
}); | ||
result.IsSuccess.Should().BeFalse(); | ||
result.Error.Should().Be(errorValue); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,7 +50,16 @@ public static Maybe<T> Where<T>(this Maybe<T> maybe, Func<T, bool> predicate) | |
|
||
return Maybe<T>.None; | ||
} | ||
public static Result<K> Select<T, K>(this Result<T> maybe, Func<T, K> selector) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't add |
||
{ | ||
return maybe.Map(selector); | ||
} | ||
|
||
[Obsolete("Use Bind instead of this method")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, no need to add new obsolete methods |
||
public static Result<K> Select<T, K>(this Result<T> maybe, Func<T, Result<K>> selector) | ||
{ | ||
return maybe.Bind(selector); | ||
} | ||
public static Maybe<K> Select<T, K>(this Maybe<T> maybe, Func<T, K> selector) | ||
{ | ||
return maybe.Map(selector); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace CSharpFunctionalExtensions | ||
{ | ||
public partial struct Result | ||
{ | ||
|
||
/// <summary> | ||
/// Combines several results (and any error messages) into a single result. | ||
/// The returned result will be a failure if any of the input <paramref name="results"/> are failures. | ||
/// Error message will have the first value of the failure operation | ||
/// </summary> | ||
/// <typeparam name="TReturnData">Type we will map</typeparam> | ||
/// <typeparam name="TDataA">Type of the function <paramref name="a"/></typeparam> | ||
/// <typeparam name="TDataB">>Type of the function <paramref name="b"/></typeparam> | ||
/// <param name="a">First function that we want to execute</param> | ||
/// <param name="b">Second function that we want to execute</param> | ||
/// <param name="combineFunction">Functional to map all the result into <paramref name="TReturnData"/> </param> | ||
/// <returns></returns> | ||
public static async Task<Result<TReturnData>> CombineSequential<TReturnData, TDataA, TDataB>( | ||
Func<Task<Result<TDataA>>> a, | ||
Func<Task<Result<TDataB>>> b, | ||
Func<(TDataA DataA, TDataB DataB), TReturnData> combineFunction) | ||
=> await (await a()) | ||
.Bind(async resultA => (await b()).Map(resultB => combineFunction((resultA, resultB)))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Such one-lines are hard to read. Please decompose into several lines, such as: {
var resultA = await a();
var resultB = await b();
// Bind, Map, etc
} |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor (nit): the indentation is off.