This adds a none generic result type and refactors the result to be a class. The Result has the same inheritance like `Task` and `Task<T>`
1059 lines
35 KiB
C#
1059 lines
35 KiB
C#
// Copyright (c) The Geekeey Authors
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
using System.Diagnostics.Contracts;
|
|
|
|
namespace Geekeey.Request.Result;
|
|
|
|
public partial class Result<T>
|
|
{
|
|
/// <summary>
|
|
/// Maps the success value of the result using a mapping function, or does nothing if the result is a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A new result containing either the mapped success value or the failure value of the original
|
|
/// result.</returns>
|
|
[Pure]
|
|
public Result<TNew> Map<TNew>(Func<T, TNew> func)
|
|
{
|
|
return IsSuccess ? new Result<TNew>(func(Value)) : new Result<TNew>(Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to map the success value of the result using a mapping function, or does nothing if the result is a
|
|
/// failure. If the mapping function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A new result containing either the mapped value, the exception thrown by <paramref name="func"/>
|
|
/// wrapped in an <see cref="ExceptionError"/>, or the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Result<TNew> TryMap<TNew>(Func<T, TNew> func)
|
|
{
|
|
try
|
|
{
|
|
return Map(func);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success value of the result to a new result using a mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value to a new result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A result which is either the mapped result or a new result containing the failure value of the original
|
|
/// result.</returns>
|
|
[Pure]
|
|
public Result<TNew> Then<TNew>(Func<T, Result<TNew>> func)
|
|
{
|
|
return IsSuccess ? func(Value) : new Result<TNew>(Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to map the success value of the result to a new result using a mapping function, or does nothing if the result
|
|
/// is a failure. If the mapping function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value to a new result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A result which is either the mapped result, the exception thrown by <paramref name="func"/> wrapped in
|
|
/// an <see cref="ExceptionError"/>, or a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Result<TNew> ThenTry<TNew>(Func<T, Result<TNew>> func)
|
|
{
|
|
try
|
|
{
|
|
return Then(func);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result<T>
|
|
{
|
|
/// <summary>
|
|
/// Maps the success value of the result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result and constructing a new result containing the mapped value, or completes
|
|
/// synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> MapAsync<TNew>(Func<T, Task<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<TNew> task)
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success value of the result using an asynchronous mapping function, or does nothing if the result is a
|
|
/// failure. If the mapping function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result and constructing a new result containing the mapped value, returning any exception
|
|
/// thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/> or completes synchronously by
|
|
/// returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> TryMapAsync<TNew>(Func<T, Task<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<TNew> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success value of the result to a new result using an asynchronous mapping function, or does nothing if
|
|
/// the result is a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value to a new result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result, or completes synchronously by returning a new result containing the failure
|
|
/// value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> ThenAsync<TNew>(Func<T, Task<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<Result<TNew>> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success value of the result to a new result using an asynchronous mapping function, or does nothing if
|
|
/// the result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value to a new result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result, returning any exception thrown by <paramref name="func"/> wrapped in an
|
|
/// <see cref="ExceptionError"/>, or completes synchronously by returning a new result containing the failure value
|
|
/// of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> ThenTryAsync<TNew>(Func<T, Task<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<Result<TNew>> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result<T>
|
|
{
|
|
/// <summary>
|
|
/// Maps the success value of the result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result and constructing a new result containing the mapped value, or completes
|
|
/// synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> MapAsync<TNew>(Func<T, ValueTask<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<TNew> task)
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success value of the result using an asynchronous mapping function, or does nothing if the result is a
|
|
/// failure. If the mapping function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result and constructing a new result containing the mapped value, returning any exception
|
|
/// thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/> or completes synchronously by
|
|
/// returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> TryMapAsync<TNew>(Func<T, ValueTask<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<TNew> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success value of the result to a new result using an asynchronous mapping function, or does nothing if
|
|
/// the result is a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value to a new result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result, or completes synchronously by returning a new result containing the failure
|
|
/// value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> ThenAsync<TNew>(Func<T, ValueTask<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<Result<TNew>> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success value of the result to a new result using an asynchronous mapping function, or does nothing if
|
|
/// the result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success value to a new result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function on
|
|
/// the success value of the result, returning any exception thrown by <paramref name="func"/> wrapped in an
|
|
/// <see cref="ExceptionError"/>, or completes synchronously by returning a new result containing the failure value
|
|
/// of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> ThenTryAsync<TNew>(Func<T, ValueTask<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<Result<TNew>> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result<T>
|
|
{
|
|
/// <summary>
|
|
/// Chains a non-generic result to this result if it is a success, or does nothing if the result is a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A result which is either the mapped result or a new result containing the failure value of the original
|
|
/// result.</returns>
|
|
[Pure]
|
|
public Result Then(Func<T, Result> func)
|
|
{
|
|
return IsSuccess ? func(Value) : new Result(Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain a non-generic result to this result if it is a success, or does nothing if the result is a
|
|
/// failure. If the function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A result which is either the mapped result, the exception thrown by <paramref name="func"/> wrapped in
|
|
/// an <see cref="ExceptionError"/>, or a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Result ThenTry(Func<T, Result> func)
|
|
{
|
|
try
|
|
{
|
|
return Then(func);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result<T>
|
|
{
|
|
/// <summary>
|
|
/// Chains a non-generic result to this result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result> ThenAsync(Func<T, Task<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result(Error));
|
|
}
|
|
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
|
|
static async Task<Result> CreateResult(Task<Result> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain a non-generic result to this result using an asynchronous mapping function, or does nothing if the
|
|
/// result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function,
|
|
/// returning any exception thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/>, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result> ThenTryAsync(Func<T, Task<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return Task.FromResult(new Result(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async Task<Result> CreateResult(Task<Result> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result<T>
|
|
{
|
|
/// <summary>
|
|
/// Chains a non-generic result to this result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result> ThenAsync(Func<T, ValueTask<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result(Error));
|
|
}
|
|
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
|
|
static async ValueTask<Result> CreateResult(ValueTask<Result> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain a non-generic result to this result using an asynchronous mapping function, or does nothing if the
|
|
/// result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function,
|
|
/// returning any exception thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/>, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result> ThenTryAsync(Func<T, ValueTask<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func(Value);
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return ValueTask.FromResult(new Result(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async ValueTask<Result> CreateResult(ValueTask<Result> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result
|
|
{
|
|
/// <summary>
|
|
/// Maps the success of the result to a new success value using a mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success to a new value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A new result containing either the mapped success value or the failure value of the original
|
|
/// result.</returns>
|
|
[Pure]
|
|
public Result<TNew> Map<TNew>(Func<TNew> func)
|
|
{
|
|
return IsSuccess ? new Result<TNew>(func()) : new Result<TNew>(Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to map the success of the result to a new success value using a mapping function, or does nothing if the
|
|
/// result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success to a new value.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A new result containing either the mapped value, the exception thrown by <paramref name="func"/>
|
|
/// wrapped in an <see cref="ExceptionError"/>, or the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Result<TNew> TryMap<TNew>(Func<TNew> func)
|
|
{
|
|
try
|
|
{
|
|
return Map(func);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chains another result to this result if it is a success, or does nothing if the result is a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A result which is either the mapped result or a new result containing the failure value of the original
|
|
/// result.</returns>
|
|
[Pure]
|
|
public Result Then(Func<Result> func)
|
|
{
|
|
return IsSuccess ? func() : new Result(Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain another result to this result if it is a success, or does nothing if the result is a failure. If
|
|
/// the function throws an exception, the exception will be returned wrapped in an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A result which is either the mapped result, the exception thrown by <paramref name="func"/> wrapped in
|
|
/// an <see cref="ExceptionError"/>, or a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Result ThenTry(Func<Result> func)
|
|
{
|
|
try
|
|
{
|
|
return Then(func);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result(new ExceptionError(exception));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chains a generic result to this result if it is a success, or does nothing if the result is a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next generic result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A result which is either the mapped result or a new result containing the failure value of the original
|
|
/// result.</returns>
|
|
[Pure]
|
|
public Result<TNew> Then<TNew>(Func<Result<TNew>> func)
|
|
{
|
|
return IsSuccess ? func() : new Result<TNew>(Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain a generic result to this result if it is a success, or does nothing if the result is a failure. If
|
|
/// the function throws an exception, the exception will be returned wrapped in an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next generic result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A result which is either the mapped result, the exception thrown by <paramref name="func"/> wrapped in
|
|
/// an <see cref="ExceptionError"/>, or a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Result<TNew> ThenTry<TNew>(Func<Result<TNew>> func)
|
|
{
|
|
try
|
|
{
|
|
return Then(func);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result
|
|
{
|
|
/// <summary>
|
|
/// Maps the success of the result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function and
|
|
/// constructing a new result containing the mapped value, or completes synchronously by returning a new result
|
|
/// containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> MapAsync<TNew>(Func<Task<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func();
|
|
return CreateResult(task);
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<TNew> task)
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success of the result using an asynchronous mapping function, or does nothing if the result is a
|
|
/// failure. If the mapping function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function and
|
|
/// constructing a new result containing the mapped value, returning any exception thrown by <paramref name="func"/>
|
|
/// wrapped in an <see cref="ExceptionError"/> or completes synchronously by returning a new result containing the
|
|
/// failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> TryMapAsync<TNew>(Func<Task<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func();
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<TNew> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chains another result to this result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result> ThenAsync(Func<Task<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result(Error));
|
|
}
|
|
|
|
var task = func();
|
|
return CreateResult(task);
|
|
|
|
static async Task<Result> CreateResult(Task<Result> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain another result to this result using an asynchronous mapping function, or does nothing if the
|
|
/// result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function,
|
|
/// returning any exception thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/>, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result> ThenTryAsync(Func<Task<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func();
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return Task.FromResult(new Result(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async Task<Result> CreateResult(Task<Result> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chains a generic result to this result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> ThenAsync<TNew>(Func<Task<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func();
|
|
return CreateResult(task);
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<Result<TNew>> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain a generic result to this result using an asynchronous mapping function, or does nothing if the
|
|
/// result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="Task{T}"/> which either completes asynchronously by invoking the mapping function,
|
|
/// returning any exception thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/>, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public Task<Result<TNew>> ThenTryAsync<TNew>(Func<Task<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func();
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return Task.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async Task<Result<TNew>> CreateResult(Task<Result<TNew>> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public partial class Result
|
|
{
|
|
/// <summary>
|
|
/// Maps the success of the result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function and
|
|
/// constructing a new result containing the mapped value, or completes synchronously by returning a new result
|
|
/// containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> MapAsync<TNew>(Func<ValueTask<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func();
|
|
return CreateResult(task);
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<TNew> task)
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maps the success of the result using an asynchronous mapping function, or does nothing if the result is a
|
|
/// failure. If the mapping function throws an exception, the exception will be returned wrapped in an
|
|
/// <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to map the success.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function and
|
|
/// constructing a new result containing the mapped value, returning any exception thrown by <paramref name="func"/>
|
|
/// wrapped in an <see cref="ExceptionError"/> or completes synchronously by returning a new result containing the
|
|
/// failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> TryMapAsync<TNew>(Func<ValueTask<TNew>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func();
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<TNew> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return new Result<TNew>(value);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chains another result to this result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result> ThenAsync(Func<ValueTask<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result(Error));
|
|
}
|
|
|
|
var task = func();
|
|
return CreateResult(task);
|
|
|
|
static async ValueTask<Result> CreateResult(ValueTask<Result> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain another result to this result using an asynchronous mapping function, or does nothing if the
|
|
/// result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function,
|
|
/// returning any exception thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/>, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result> ThenTryAsync(Func<ValueTask<Result>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func();
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return ValueTask.FromResult(new Result(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async ValueTask<Result> CreateResult(ValueTask<Result> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chains a generic result to this result using an asynchronous mapping function, or does nothing if the result is
|
|
/// a failure.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> ThenAsync<TNew>(Func<ValueTask<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
var task = func();
|
|
return CreateResult(task);
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<Result<TNew>> task)
|
|
{
|
|
var result = await task;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to chain a generic result to this result using an asynchronous mapping function, or does nothing if the
|
|
/// result is a failure. If the mapping function throws an exception, the exception will be returned wrapped in
|
|
/// an <see cref="ExceptionError"/>.
|
|
/// </summary>
|
|
/// <param name="func">The function used to create the next result.</param>
|
|
/// <typeparam name="TNew">The type of the new value.</typeparam>
|
|
/// <returns>A <see cref="ValueTask{T}"/> which either completes asynchronously by invoking the mapping function,
|
|
/// returning any exception thrown by <paramref name="func"/> wrapped in an <see cref="ExceptionError"/>, or
|
|
/// completes synchronously by returning a new result containing the failure value of the original result.</returns>
|
|
[Pure]
|
|
public ValueTask<Result<TNew>> ThenTryAsync<TNew>(Func<ValueTask<Result<TNew>>> func)
|
|
{
|
|
if (!IsSuccess)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(Error));
|
|
}
|
|
|
|
try
|
|
{
|
|
var task = func();
|
|
return CreateResult(task);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return ValueTask.FromResult(new Result<TNew>(new ExceptionError(exception)));
|
|
}
|
|
|
|
static async ValueTask<Result<TNew>> CreateResult(ValueTask<Result<TNew>> task)
|
|
{
|
|
try
|
|
{
|
|
var value = await task;
|
|
return value;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return new Result<TNew>(new ExceptionError(exception));
|
|
}
|
|
}
|
|
}
|
|
}
|