Skip to content
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

Some result additions #1

Merged
merged 5 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Results.Tests/DotNetThoughts.Results.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
<PackageReference Include="xunit.core" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit.core" Version="2.6.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
224 changes: 207 additions & 17 deletions Results/BindAll.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,27 @@ public static Result<Unit> BindAll<T>(this Result<IEnumerable<T>> source, Func<T
}
}

public static Result<Unit> BindAll<T>(this Result<IEnumerable<T>> source, Func<T, int, Result<Unit>> next)
{
if (source.Success)
{
var results = new List<Result<Unit>>();
var index = 0;
foreach (var s in source.Value)
{
results.Add(next(s, index));
index++;
}
return results.Any(x => !x.Success)
? UnitResult.Error(results.SelectMany(x => x.Errors))
: UnitResult.Ok;
}
else
{
return Result<Unit>.Error(source.Errors);
}
}

public static async Task<Result<Unit>> BindAll<T>(this Result<IEnumerable<T>> source, Func<T, Task<Result<Unit>>> next)
{
if (source.Success)
Expand All @@ -42,6 +63,27 @@ public static async Task<Result<Unit>> BindAll<T>(this Result<IEnumerable<T>> so
}
}

public static async Task<Result<Unit>> BindAll<T>(this Result<IEnumerable<T>> source, Func<T, int, Task<Result<Unit>>> next)
{
if (source.Success)
{
var results = new List<Result<Unit>>();
var index = 0;
foreach (var s in source.Value)
{
results.Add(await next(s, index));
index++;
}
return results.Any(x => !x.Success)
? UnitResult.Error(results.SelectMany(x => x.Errors))
: UnitResult.Ok;
}
else
{
return Result<Unit>.Error(source.Errors);
}
}

/// <summary>
/// Does not short circuit. Returns all errors or all results
/// </summary>
Expand All @@ -65,35 +107,117 @@ public static Result<List<TResult>> BindAll<T, TResult>(this Result<IEnumerable<
}
}

[Obsolete("Does not take a Result as input. Use one of the regular extensions that takes a result as input. (Do a .Return() on your non-result object first)")]
public static Result<List<TResult>> BindAll<T, TResult>(this IEnumerable<T> source, Func<T, Result<TResult>> next)
public static Result<List<TResult>> BindAll<T, TResult>(this Result<IEnumerable<T>> source, Func<T, int, Result<TResult>> next)
mattiasnordqvist marked this conversation as resolved.
Show resolved Hide resolved
{
if (source.Success)
{
var results = new List<Result<TResult>>();
var index = 0;
foreach (var s in source.Value)
{
results.Add(next(s, index));
index++;
}
return results.Any(x => !x.Success)
? Result<List<TResult>>.Error(results.SelectMany(x => x.Errors))
: Result<List<TResult>>.Ok(results.Select(x => x.Value).ToList());
}
else
{
return Result<List<TResult>>.Error(source.Errors);
}
}

/// <summary>
/// Does not short circuit. Returns all errors or all results
/// </summary>
public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this Result<IEnumerable<T>> source, Func<T, Task<Result<TResult>>> next)
{
var results = new List<Result<TResult>>();
if (source.Success)
{
var results = new List<Result<TResult>>();

foreach (var s in source)
foreach (var s in source.Value)
{
results.Add(await next(s));
}
return results.Any(x => !x.Success)
? Result<List<TResult>>.Error(results.SelectMany(x => x.Errors))
: Result<List<TResult>>.Ok(results.Select(x => x.Value).ToList());
}
else
{
results.Add(next(s));
return Result<List<TResult>>.Error(source.Errors);
}
return results.Any(x => !x.Success)
? Result<List<TResult>>.Error(results.SelectMany(x => x.Errors))
: Result<List<TResult>>.Ok(results.Select(x => x.Value).ToList());
}

[Obsolete("Does not take a Result as input. Use one of the regular extensions that takes a result as input. (Do a .Return() on your non-result object first)")]
public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this IEnumerable<T> source, Func<T, Task<Result<TResult>>> next)
public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this Result<IEnumerable<T>> source, Func<T, int, Task<Result<TResult>>> next)
{
if (source.Success)
{
var results = new List<Result<TResult>>();
var index = 0;
foreach (var s in source.Value)
{
results.Add(await next(s, index));
index++;
}
return results.Any(x => !x.Success)
? Result<List<TResult>>.Error(results.SelectMany(x => x.Errors))
: Result<List<TResult>>.Ok(results.Select(x => x.Value).ToList());
}
else
{
return Result<List<TResult>>.Error(source.Errors);
}
}

////// Same as above, but from tasks


/// <summary>
/// Does not short circuit. Returns all errors or one unit
/// </summary>
public static async Task<Result<Unit>> BindAll<T>(this Task<Result<IEnumerable<T>>> source, Func<T, Result<Unit>> next)
{
var results = new List<Result<TResult>>();
if ((await source).Success)
{
var results = new List<Result<Unit>>();
foreach (var s in (await source).Value)
{
results.Add(next(s));
}
return results.Any(x => !x.Success)
? UnitResult.Error(results.SelectMany(x => x.Errors))
: UnitResult.Ok;
}
else
{
return Result<Unit>.Error((await source).Errors);
}
}

foreach (var s in source)
public static async Task<Result<Unit>> BindAll<T>(this Task<Result<IEnumerable<T>>> source, Func<T, int, Result<Unit>> next)
{
if ((await source).Success)
{
results.Add(await next(s));
var results = new List<Result<Unit>>();
var index = 0;
foreach (var s in (await source).Value)
{
results.Add(next(s, index));
index++;
}
return results.Any(x => !x.Success)
? UnitResult.Error(results.SelectMany(x => x.Errors))
: UnitResult.Ok;
}
else
{
return Result<Unit>.Error((await source).Errors);
}
return results.Any(x => !x.Success)
? Result<List<TResult>>.Error(results.SelectMany(x => x.Errors))
: Result<List<TResult>>.Ok(results.Select(x => x.Value).ToList());
}

// with tasks
public static async Task<Result<Unit>> BindAll<T>(this Task<Result<IEnumerable<T>>> source, Func<T, Task<Result<Unit>>> next)
{
if ((await source).Success)
Expand All @@ -113,6 +237,27 @@ public static async Task<Result<Unit>> BindAll<T>(this Task<Result<IEnumerable<T
}
}

public static async Task<Result<Unit>> BindAll<T>(this Task<Result<IEnumerable<T>>> source, Func<T, int, Task<Result<Unit>>> next)
{
if ((await source).Success)
{
var results = new List<Result<Unit>>();
var index = 0;
foreach (var s in (await source).Value)
{
results.Add(await next(s, index));
index++;
}
return results.Any(x => !x.Success)
? UnitResult.Error(results.SelectMany(x => x.Errors))
: UnitResult.Ok;
}
else
{
return Result<Unit>.Error((await source).Errors);
}
}

/// <summary>
/// Does not short circuit. Returns all errors or all results
/// </summary>
Expand All @@ -136,6 +281,30 @@ public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this Task<Re
}
}

public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this Task<Result<IEnumerable<T>>> source, Func<T, int, Result<TResult>> next)
{
if ((await source).Success)
{
var results = new List<Result<TResult>>();
var index = 0;
foreach (var s in (await source).Value)
{
results.Add(next(s, index));
index++;
}
return results.Any(x => !x.Success)
? Result<List<TResult>>.Error(results.SelectMany(x => x.Errors))
: Result<List<TResult>>.Ok(results.Select(x => x.Value).ToList());
}
else
{
return Result<List<TResult>>.Error((await source).Errors);
}
}

/// <summary>
/// Does not short circuit. Returns all errors or all results
/// </summary>
public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this Task<Result<IEnumerable<T>>> source, Func<T, Task<Result<TResult>>> next)
{
if ((await source).Success)
Expand All @@ -155,4 +324,25 @@ public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this Task<Re
return Result<List<TResult>>.Error((await source).Errors);
}
}

public static async Task<Result<List<TResult>>> BindAll<T, TResult>(this Task<Result<IEnumerable<T>>> source, Func<T, int, Task<Result<TResult>>> next)
{
if ((await source).Success)
{
var results = new List<Result<TResult>>();
var index = 0;
foreach (var s in (await source).Value)
{
results.Add(await next(s, index));
index++;
}
return results.Any(x => !x.Success)
? Result<List<TResult>>.Error(results.SelectMany(x => x.Errors))
: Result<List<TResult>>.Ok(results.Select(x => x.Value).ToList());
}
else
{
return Result<List<TResult>>.Error((await source).Errors);
}
}
}
44 changes: 0 additions & 44 deletions Results/BindEach.cs
Original file line number Diff line number Diff line change
@@ -1,50 +1,6 @@
namespace DotNetThoughts.Results;
public static partial class Extensions
{
/// <summary>
/// Short circuits on failure
/// </summary>
[Obsolete("Does not take a Result as input. Use one of the regular extensions that takes a result as input. (Do a .Return() on your non-result object first)")]
public static Result<Unit> BindEach<T>(this IEnumerable<T> source, Func<T, Result<Unit>> next)
{
foreach (var s in source)
{
var result = next(s);
if (!result.Success) return result;
}
return UnitResult.Ok;
}

/// <summary>
/// Short circuits on failure
/// </summary>
[Obsolete("Does not take a Result as input. Use one of the regular extensions that takes a result as input. (Do a .Return() on your non-result object first)")]
public static async Task<Result<Unit>> BindEach<T>(this IEnumerable<T> source, Func<T, Task<Result<Unit>>> next)
{
foreach (var s in source)
{
var result = await next(s);
if (!result.Success) return result;
}
return UnitResult.Ok;
}

/// <summary>
/// Short circuits on failure
/// </summary>
[Obsolete("Does not take a Result as input. Use one of the regular extensions that takes a result as input. (Do a .Return() on your non-result object first)")]
public static Result<List<TResult>> BindEach<T, TResult>(this IEnumerable<T> source, Func<T, Result<TResult>> next)
{
var result = new List<TResult>();
foreach (var s in source)
{
var r = next(s);
if (!r.Success) return Result<List<TResult>>.Error(r.Errors);
result.Add(r.Value);
}
return Result<List<TResult>>.Ok(result);
}

/// <summary>
/// Short circuits on failure
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions Results/DotNetThoughts.Results.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>1.4.3</Version>
<Version>1.5.0</Version>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
Expand Down
17 changes: 15 additions & 2 deletions Results/ErrorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,26 @@ public string Type
/// </summary>
public string Message { get; protected set; }

private Dictionary<string, object?> _data = [];

/// <summary>
/// Scans the inheriting type for all properties and returns them as a dictionary where property name is key, and the property value is the value.
/// In addition to data you add yourself, this also contains all properties on the inheriting type with property name as key and property value as value.
/// If you add a key to this dictionary, where the inheriting type has a property with the same name as your key, the value of that dictionary entry will be overwritten by the value of the property.
/// </summary>
/// <returns></returns>
public Dictionary<string, object?> Data { get => GetData(); }
mattiasnordqvist marked this conversation as resolved.
Show resolved Hide resolved

[Pure]
public Dictionary<string, object?> GetData() => GetType()
public Dictionary<string, object?> GetData()
{
var propValues = GetType()
.GetProperties()
.Where(p => p.DeclaringType != typeof(IError) && p.DeclaringType != typeof(ErrorBase))
.ToDictionary(d => d.Name, d => d.GetValue(this));
foreach (var prop in propValues)
{
_data[prop.Key] = prop.Value;
}
return _data;
}
}
Loading
Loading