From 94ad6e57d718e9b2659f10c752cf18a4fe12b700 Mon Sep 17 00:00:00 2001 From: Robin Ehlert Date: Wed, 23 Jul 2025 08:43:59 +0200 Subject: [PATCH] Add initial project structure with Result type and extension methods --- .gitignore | 6 + Rehlert.RoP.sln | 16 +++ Rehlert.RoP/Extensions/FallbackExtensions.cs | 28 +++++ Rehlert.RoP/Extensions/OnErrorExtensions.cs | 55 ++++++++ Rehlert.RoP/Extensions/OnSuccessExtensions.cs | 118 ++++++++++++++++++ Rehlert.RoP/Rehlert.RoP.csproj | 13 ++ Rehlert.RoP/Result.cs | 13 ++ 7 files changed, 249 insertions(+) create mode 100644 .gitignore create mode 100644 Rehlert.RoP.sln create mode 100644 Rehlert.RoP/Extensions/FallbackExtensions.cs create mode 100644 Rehlert.RoP/Extensions/OnErrorExtensions.cs create mode 100644 Rehlert.RoP/Extensions/OnSuccessExtensions.cs create mode 100644 Rehlert.RoP/Rehlert.RoP.csproj create mode 100644 Rehlert.RoP/Result.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da23fc0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin/ +obj/ +.idea/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ diff --git a/Rehlert.RoP.sln b/Rehlert.RoP.sln new file mode 100644 index 0000000..983aa99 --- /dev/null +++ b/Rehlert.RoP.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rehlert.RoP", "Rehlert.RoP\Rehlert.RoP.csproj", "{C043B9E4-712D-4710-972E-1D89A31A9E2D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C043B9E4-712D-4710-972E-1D89A31A9E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C043B9E4-712D-4710-972E-1D89A31A9E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C043B9E4-712D-4710-972E-1D89A31A9E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C043B9E4-712D-4710-972E-1D89A31A9E2D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Rehlert.RoP/Extensions/FallbackExtensions.cs b/Rehlert.RoP/Extensions/FallbackExtensions.cs new file mode 100644 index 0000000..a3ff0ae --- /dev/null +++ b/Rehlert.RoP/Extensions/FallbackExtensions.cs @@ -0,0 +1,28 @@ +namespace Rehlert.RoP.Extensions; + +public static class FallbackExtensions +{ + public static TIn FallbackWith(this Result value, TIn defaultValue) + { + var result = value.Match( + ok => ok.Value, + _ => defaultValue + ); + + return result; + } + + public static async Task FallbackWith( + this Task> value, + TIn defaultValue + ) + { + var valRes = await value; + var result = valRes.Match( + ok => ok.Value, + _ => defaultValue + ); + + return result; + } +} \ No newline at end of file diff --git a/Rehlert.RoP/Extensions/OnErrorExtensions.cs b/Rehlert.RoP/Extensions/OnErrorExtensions.cs new file mode 100644 index 0000000..e111bc1 --- /dev/null +++ b/Rehlert.RoP/Extensions/OnErrorExtensions.cs @@ -0,0 +1,55 @@ +namespace Rehlert.RoP.Extensions; + +public static class OnErrorExtensions +{ + public static Result OnError(this Result value, Action action) + { + value.Match( + _ => { }, + err => action(err.Value) + ); + + return value; + } + + public static async Task> OnError( + this Result value, + Func func + ) + { + await value.Match( + _ => Task.CompletedTask, + err => func(err.Value) + ); + + return value; + } + + public static async Task> OnError( + this Task> value, + Func func + ) + { + var valRes = await value; + await valRes.Match( + _ => Task.CompletedTask, + err => func(err.Value) + ); + + return valRes; + } + + public static async Task> OnError( + this Task> value, + Action action + ) + { + var valRes = await value; + valRes.Match( + _ => { }, + err => action(err.Value) + ); + + return valRes; + } +} \ No newline at end of file diff --git a/Rehlert.RoP/Extensions/OnSuccessExtensions.cs b/Rehlert.RoP/Extensions/OnSuccessExtensions.cs new file mode 100644 index 0000000..6e61777 --- /dev/null +++ b/Rehlert.RoP/Extensions/OnSuccessExtensions.cs @@ -0,0 +1,118 @@ +namespace Rehlert.RoP.Extensions; + +public static class OnSuccessExtensions +{ + public static Result OnSuccess(this Result value, + Func> func) + { + var result = value.Match( + ok => func(ok.Value), + err => err.Value + ); + + return result; + } + + public static async Task> OnSuccess( + this Result value, + Func>> func + ) + { + var result = await value.Match( + ok => func(ok.Value), + err => Task.FromResult>(err.Value) + ); + + return result; + } + + public static async Task> OnSuccess( + this Task> value, + Func>> func + ) + { + var valRes = await value; + var result = await valRes.Match( + ok => func(ok.Value), + err => Task.FromResult>(err.Value) + ); + + return result; + } + + public static async Task> OnSuccess( + this Task> value, + Func> func + ) + { + var valRes = await value; + var result = valRes.Match( + ok => func(ok.Value), + err => err.Value + ); + + return result; + } + + public static async Task OnSuccess( + this Task> value, + Func func + ) + { + var valRes = await value; + await valRes.Match( + ok => func(ok.Value), + err => Task.CompletedTask + ); + } + + public static async Task OnSuccess( + this Task> value, + Action action + ) + { + var valRes = await value; + valRes.Match( + ok => action(ok.Value), + _ => { } + ); + } + + public static async Task OnSuccess( + this Result value, + Func func + ) + { + await value.Match( + ok => func(ok.Value), + _ => Task.CompletedTask + ); + } + + public static void OnSuccess( + this Result value, + Action action + ) + { + value.Match( + ok => action(ok.Value), + _ => { } + ); + } + + public static Result<(T1, T2), TErr> Combine(this Result r1, Result r2) + { + if (r1 is Result.Error err) + return err.Value; + if (r2 is Result.Error err2) + return err2.Value; + return (r1.UnwrapOk().Value, r2.UnwrapOk().Value); + } + + public static async Task> Combine(this Task> r1, + Result r2) + { + var val = await r1; + return val.Combine(r2); + } +} \ No newline at end of file diff --git a/Rehlert.RoP/Rehlert.RoP.csproj b/Rehlert.RoP/Rehlert.RoP.csproj new file mode 100644 index 0000000..32f509e --- /dev/null +++ b/Rehlert.RoP/Rehlert.RoP.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/Rehlert.RoP/Result.cs b/Rehlert.RoP/Result.cs new file mode 100644 index 0000000..949cb3a --- /dev/null +++ b/Rehlert.RoP/Result.cs @@ -0,0 +1,13 @@ +using Dunet; + +namespace Rehlert.RoP; + +[Union] +public partial record Result + where TOk : notnull + where TError : notnull +{ + public partial record Ok(TOk Value); + + public partial record Error(TError Value); +} \ No newline at end of file