-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added Railway-oriented extension methods (Ensure, EnsureNotNull, Then, Tap, And) * Fixed .editorconfig
- Loading branch information
1 parent
8f42ff5
commit b9a83e6
Showing
11 changed files
with
560 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace RailwayResult.FunctionExtensions; | ||
|
||
public interface IRuleWithError<T> | ||
{ | ||
public Result<T> Apply(T val); | ||
} |
8 changes: 8 additions & 0 deletions
8
RailwayResult.FunctionExtensions/RailwayResult.FunctionExtensions.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\src\RailwayResult.Errors\RailwayResult.Errors.csproj" /> | ||
<ProjectReference Include="..\src\RailwayResult\RailwayResult.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
namespace RailwayResult.FunctionExtensions; | ||
|
||
public static partial class ResultExtensions | ||
{ | ||
public static Result<(TFirst, TSecond)> And<TFirst, TSecond>(this Result<TFirst> result, Func<TSecond> func) | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
return (result.Value, func()); | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> And<TFirst, TSecond>(this Task<Result<TFirst>> resultTask, Func<TSecond> func) | ||
{ | ||
var result = await resultTask; | ||
return result.And(func); | ||
} | ||
|
||
public static Result<(TFirst, TSecond)> And<TFirst, TSecond>(this Result<TFirst> result, Func<Result<TSecond>> func) | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
var nestedResult = func(); | ||
if (nestedResult.IsFailure) | ||
return nestedResult.Error; | ||
|
||
return (result.Value, nestedResult.Value); | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> And<TFirst, TSecond>(this Task<Result<TFirst>> resultTask, Func<Result<TSecond>> func) | ||
{ | ||
var result = await resultTask; | ||
return result.And(func); | ||
} | ||
|
||
public static Result<(TFirst, TSecond)> And<TFirst, TSecond>(this Result<TFirst> result, Func<TFirst, Result<TSecond>> func) | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
var nestedResult = func(result.Value); | ||
if (nestedResult.IsFailure) | ||
return nestedResult.Error; | ||
|
||
return (result.Value, nestedResult.Value); | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> And<TFirst, TSecond>(this Task<Result<TFirst>> resultTask, Func<TFirst, Result<TSecond>> func) | ||
{ | ||
var result = await resultTask; | ||
return result.And(func); | ||
} | ||
|
||
public static Result<(TFirst, TSecond, TThird)> And<TFirst, TSecond, TThird>(this Result<(TFirst, TSecond)> result, Func<TFirst, TSecond, Result<TThird>> func) | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
var nestedResult = func(result.Value.Item1, result.Value.Item2); | ||
if (nestedResult.IsFailure) | ||
return nestedResult.Error; | ||
|
||
return (result.Value.Item1, result.Value.Item2, nestedResult.Value); | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond, TThird)>> And<TFirst, TSecond, TThird>(this Task<Result<(TFirst, TSecond)>> resultTask, Func<TFirst, TSecond, Result<TThird>> func) | ||
{ | ||
var result = await resultTask; | ||
return result.And(func); | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> AndAsync<TFirst, TSecond>(this Result<TFirst> result, Func<TFirst, Task<TSecond>> asyncFunc) | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
return (result.Value, await asyncFunc(result.Value)); | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> AndAsync<TFirst, TSecond>(this Task<Result<TFirst>> resultTask, Func<TFirst, Task<TSecond>> asyncFunc) | ||
{ | ||
var result = await resultTask; | ||
return await result.AndAsync(asyncFunc); | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
RailwayResult.FunctionExtensions/ResultExtensions.Ensure.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
namespace RailwayResult.FunctionExtensions; | ||
|
||
public static partial class ResultExtensions | ||
{ | ||
public static Result<TObj> Ensure<TObj, TError>(this TObj obj, Rule<TObj> rule, TError error) where TError : ErrorBase | ||
{ | ||
if (!rule(obj)) | ||
return error; | ||
|
||
return obj; | ||
} | ||
|
||
public static async Task<Result<TObj>> Ensure<TObj, TError>(this Task<TObj> objTask, Rule<TObj> rule, TError error) where TError : ErrorBase | ||
{ | ||
var obj = await objTask; | ||
return obj.Ensure(rule, error); | ||
} | ||
|
||
public static Result<TObj> Ensure<TObj, TRule>(this TObj obj, params TRule[] rules) where TRule : IRuleWithError<TObj> | ||
{ | ||
foreach (var rule in rules) | ||
{ | ||
var ruleResult = rule.Apply(obj); | ||
if (ruleResult.IsFailure) | ||
return ruleResult; | ||
} | ||
|
||
return obj; | ||
} | ||
|
||
public static async Task<Result<TObj>> Ensure<TObj, TRule>(this Task<TObj> objTask, params TRule[] rules) where TRule : IRuleWithError<TObj> | ||
{ | ||
var obj = await objTask; | ||
return obj.Ensure(rules); | ||
} | ||
|
||
public static Result<TValue> Ensure<TValue, TError>(this Result<TValue> result, Rule<TValue> rule, TError error) where TError : ErrorBase | ||
{ | ||
if (result.IsFailure) | ||
return result; | ||
|
||
if (!rule(result.Value)) | ||
return error; | ||
|
||
return result; | ||
} | ||
|
||
public static async Task<Result<TValue>> Ensure<TValue, TError>(this Task<Result<TValue>> selfTask, Rule<TValue> rule, TError error) where TError : ErrorBase | ||
{ | ||
var self = await selfTask; | ||
return self.Ensure(rule, error); | ||
} | ||
|
||
public static Result<TValue> Ensure<TValue, TRule>(this Result<TValue> result, params TRule[] rules) where TRule : IRuleWithError<TValue> | ||
{ | ||
if (result.IsFailure) | ||
return result; | ||
|
||
foreach (var rule in rules) | ||
{ | ||
var ruleResult = rule.Apply(result.Value); | ||
if (ruleResult.IsFailure) | ||
return ruleResult; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
public static async Task<Result<TValue>> Ensure<TValue, TRule>(this Task<Result<TValue>> resultTask, params TRule[] rules) where TRule : IRuleWithError<TValue> | ||
{ | ||
var result = await resultTask; | ||
return result.Ensure(rules); | ||
} | ||
|
||
public static Result<(TFirst, TSecond)> Ensure<TFirst, TSecond, TError>(this Result<(TFirst, TSecond)> result, Rule<TFirst, TSecond> rule, TError error) where TError : ErrorBase | ||
{ | ||
if (result.IsFailure) | ||
return result; | ||
|
||
if (!rule(result.Value.Item1, result.Value.Item2)) | ||
return error; | ||
|
||
return result; | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> Ensure<TFirst, TSecond, TError>(this Task<Result<(TFirst, TSecond)>> resultTask, Rule<TFirst, TSecond> rule, TError error) where TError : ErrorBase | ||
{ | ||
var result = await resultTask; | ||
return result.Ensure(rule, error); | ||
} | ||
|
||
public static Result<(TFirst, TSecond)> Ensure<TFirst, TSecond, TRule>(this Result<(TFirst, TSecond)> result, TRule rule) where TRule : IRuleWithError<(TFirst, TSecond)> | ||
{ | ||
if (result.IsFailure) | ||
return result; | ||
|
||
return rule.Apply(result.Value); | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> Ensure<TFirst, TSecond, TRule>(this Task<Result<(TFirst, TSecond)>> resultTask, TRule rule) where TRule : IRuleWithError<(TFirst, TSecond)> | ||
{ | ||
var result = await resultTask; | ||
return result.Ensure(rule); | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
RailwayResult.FunctionExtensions/ResultExtensions.EnsureNotNull.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
namespace RailwayResult.FunctionExtensions; | ||
|
||
public static partial class ResultExtensions | ||
{ | ||
public static Result<TObj> EnsureNotNull<TObj, TError>(this TObj? obj, TError error) where TError : ErrorBase | ||
{ | ||
if (obj is null) | ||
return error; | ||
|
||
return obj; | ||
} | ||
|
||
public static async Task<Result<TObj>> EnsureNotNull<TObj, TError>(this Task<TObj?> objTask, TError error) where TError : ErrorBase | ||
{ | ||
var obj = await objTask; | ||
return obj.EnsureNotNull(error); | ||
} | ||
|
||
public static Result<TValue> EnsureNotNull<TValue, TError>(this Result<TValue?> result, TError error) where TError : ErrorBase | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
if (result.Value is null) | ||
return error; | ||
|
||
return result.Value; | ||
} | ||
|
||
public static async Task<Result<TValue>> EnsureNotNull<TValue, TError>(this Task<Result<TValue?>> resultTask, TError error) where TError : ErrorBase | ||
{ | ||
var result = await resultTask; | ||
return result.EnsureNotNull(error); | ||
} | ||
|
||
public static Result<TValue> EnsureNotNull<TValue, TProperty, TError>(this Result<TValue> result, Func<TValue, TProperty?> selector, TError error) where TError : ErrorBase | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
if (selector(result.Value) is null) | ||
return error; | ||
|
||
return result.Value; | ||
} | ||
|
||
public static async Task<Result<TValue>> EnsureNotNull<TValue, TProperty, TError>(this Task<Result<TValue>> resultTask, Func<TValue, TProperty?> selector, TError error) where TError : ErrorBase | ||
{ | ||
var result = await resultTask; | ||
return result.EnsureNotNull(selector, error); | ||
} | ||
|
||
public static Result<(TFirst, TSecond)> EnsureNotNull<TFirst, TSecond, TProperty, TError>(this Result<(TFirst, TSecond)> result, Func<TFirst, TSecond, TProperty?> selector, TError error) where TError : ErrorBase | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
if (selector(result.Value.Item1, result.Value.Item2) is null) | ||
return error; | ||
|
||
return result.Value; | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> EnsureNotNull<TFirst, TSecond, TProperty, TError>(this Task<Result<(TFirst, TSecond)>> resultTask, Func<TFirst, TSecond, TProperty?> selector, TError error) where TError : ErrorBase | ||
{ | ||
var result = await resultTask; | ||
return result.EnsureNotNull(selector, error); | ||
} | ||
|
||
public static Result<(TFirst, TSecond)> EnsureSecondNotNull<TFirst, TSecond, TError>(this Result<(TFirst, TSecond?)> result, TError error) where TError : ErrorBase | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
if (result.Value.Item2 is null) | ||
return error; | ||
|
||
return result.Value!; | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> EnsureSecondNotNull<TFirst, TSecond, TError>(this Task<Result<(TFirst, TSecond?)>> resultTask, TError error) where TError : ErrorBase | ||
{ | ||
var result = await resultTask; | ||
return result.EnsureSecondNotNull(error); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
namespace RailwayResult.FunctionExtensions; | ||
|
||
public static partial class ResultExtensions | ||
{ | ||
public static Result<TValue> Tap<TValue>(this Result<TValue> result, Action<TValue> func) | ||
{ | ||
if (result.IsFailure) | ||
return result; | ||
|
||
func(result.Value); | ||
return result; | ||
} | ||
|
||
public static async Task<Result<TValue>> Tap<TValue>(this Task<Result<TValue>> resultTask, Action<TValue> func) | ||
{ | ||
var result = await resultTask; | ||
return result.Tap(func); | ||
} | ||
|
||
public static async Task<Result<TValue>> Tap<TValue>(this Task<Result<Result<TValue>>> resultTask, Action<TValue> func) | ||
{ | ||
var result = await resultTask; | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
return result.Value.Tap(func); | ||
} | ||
|
||
public static Result<(TFirst, TSecond)> Tap<TFirst, TSecond>(this Result<(TFirst, TSecond)> result, Action<TFirst, TSecond> func) | ||
{ | ||
if (result.IsFailure) | ||
return result; | ||
|
||
func(result.Value.Item1, result.Value.Item2); | ||
return result; | ||
} | ||
|
||
public static async Task<Result<(TFirst, TSecond)>> Tap<TFirst, TSecond>(this Task<Result<(TFirst, TSecond)>> resultTask, Action<TFirst, TSecond> func) | ||
{ | ||
var result = await resultTask; | ||
return result.Tap(func); | ||
} | ||
|
||
public static async Task<Result> TapAsync(this Result result, Func<Task> asyncFunc) | ||
{ | ||
if (result.IsFailure) | ||
return result.Error; | ||
|
||
await asyncFunc(); | ||
return Result.Success; | ||
} | ||
|
||
public static async Task<Result> TapAsync(this Task<Result> resultTask, Func<Task> asyncFunc) | ||
{ | ||
var result = await resultTask; | ||
return await result.TapAsync(asyncFunc); | ||
} | ||
|
||
public static async Task<Result<TValue>> TapAsync<TValue>(this Result<TValue> result, Func<TValue, Task> asyncFunc) | ||
{ | ||
if (result.IsFailure) | ||
return result; | ||
|
||
await asyncFunc(result.Value); | ||
return result; | ||
} | ||
|
||
public static async Task<Result<TValue>> TapAsync<TValue>(this Task<Result<TValue>> resultTask, Func<TValue, Task> asyncFunc) | ||
{ | ||
var result = await resultTask; | ||
return await result.TapAsync(asyncFunc); | ||
} | ||
} |
Oops, something went wrong.