Skip to content

Instantly share code, notes, and snippets.

@jvandertil
Created July 22, 2019 20:02
Show Gist options
  • Save jvandertil/e83603d7191f9bc3703e379e445933b5 to your computer and use it in GitHub Desktop.
Save jvandertil/e83603d7191f9bc3703e379e445933b5 to your computer and use it in GitHub Desktop.
public class FailureResult : IResult
{
public bool Success => false;
public string ErrorMessage { get; }
public FailureResult(string errorMessage)
{
if (string.IsNullOrWhiteSpace(errorMessage))
{
throw new ArgumentException(nameof(errorMessage) + " can not be null or whitespace.", nameof(errorMessage));
}
ErrorMessage = errorMessage;
}
}
public class FailureResult<TResult> : FailureResult, IResult<TResult>
{
public FailureResult(string errorMessage)
: base(errorMessage)
{
}
public TResult Value => throw new InvalidOperationException("Value is not available when the operation failed.");
public FailureResult<TOut> ConvertTo<TOut>()
{
if (typeof(TOut) == typeof(TResult))
{
return this as FailureResult<TOut>;
}
return new FailureResult<TOut>(ErrorMessage);
}
}
public interface IResult
{
bool Success { get; }
}
public interface IResult<out TResult> : IResult
{
TResult Value { get; }
}
public static class Result
{
private static readonly SuccessResult Success = new SuccessResult();
public static SuccessResult Ok()
{
return Success;
}
public static SuccessResult<TResult> Ok<TResult>(TResult value)
{
return new SuccessResult<TResult>(value);
}
public static FailureResult Fail(string errorMessage)
{
return new FailureResult(errorMessage);
}
public static FailureResult<TResult> Fail<TResult>(string errorMessage)
{
return new FailureResult<TResult>(errorMessage);
}
}
public static class ResultExtensions
{
public static void Match(this IResult result, Action onSuccess, Action<FailureResult> onFail)
{
if (result.Success)
{
onSuccess();
}
else
{
onFail((FailureResult)result);
}
}
public static void Match<TResult>(this IResult<TResult> result, Action<TResult> onSuccess, Action<FailureResult> onFail)
{
if (result.Success)
{
onSuccess(((SuccessResult<TResult>)result).Value);
}
else
{
onFail((FailureResult)result);
}
}
public static TOut Match<TResult, TOut>(this IResult<TResult> result, Func<TResult, TOut> onSuccess, Func<FailureResult, TOut> onFail)
{
return result.Success
? onSuccess(((SuccessResult<TResult>)result).Value)
: onFail((FailureResult)result);
}
public static IResult<TOut> OnSuccess<TResult, TOut>(this IResult<TResult> result, Func<TResult, IResult<TOut>> onSuccess)
{
if (result.Success)
{
return onSuccess(((SuccessResult<TResult>)result).Value);
}
return ((FailureResult<TResult>)result).ConvertTo<TOut>();
}
}
public class SuccessResult : IResult
{
public bool Success => true;
}
public class SuccessResult<TResult> : SuccessResult, IResult<TResult>
{
public TResult Value { get; }
public SuccessResult(TResult result)
{
Value = result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment