namespace MS.Microservice.Core.Functional
{
///
/// Exceptional 的异常分支容器。
///
public readonly struct ExceptionThrown
{
internal Exception Value { get; }
internal ExceptionThrown(Exception value)
{
ArgumentNullException.ThrowIfNull(value, nameof(value));
Value = value;
}
public override string ToString() => $"ExceptionThrown({Value.Message})";
}
///
/// Exceptional 的成功分支容器。
///
public readonly struct Success
{
internal T Value { get; }
internal Success(T value)
{
ArgumentNullException.ThrowIfNull(value, nameof(value));
Value = value;
}
public override string ToString() => $"Success({Value})";
}
///
/// Either<Exception, T> 的特定版本:ExceptionThrown 表示失败,Success 表示成功。
///
public readonly struct Exceptional : IEquatable>
{
private readonly Either _either;
private Exceptional(Either either) => _either = either;
internal Exceptional(T value) => _either = F.Right(value);
internal Exceptional(Exception ex) => _either = F.Left(ex);
public bool IsSuccess => _either.IsRight;
public bool IsException => _either.IsLeft;
public Exception Exception => IsException ? _either.Left : throw new InvalidOperationException("Exceptional 处于 Success 状态,无法读取 Exception。");
public T Success => IsSuccess ? _either.Right : throw new InvalidOperationException("Exceptional 处于 Exception 状态,无法读取 Success。");
public static implicit operator Exceptional(ExceptionThrown exception)
=> new((Either)F.Left(exception.Value));
public static implicit operator Exceptional(Success success)
=> new((Either)F.Right(success.Value));
public static implicit operator Exceptional(Either either)
=> new(either);
public static implicit operator Either(Exceptional exceptional)
=> exceptional._either;
public static implicit operator Exceptional(Exception ex)
=> new(ex);
public static implicit operator Exceptional(T value) => new(value);
public R Match(Func exception, Func success)
=> _either.Match(exception, success);
public Exceptional Map(Func mapper)
=> _either.Map(mapper);
public Exceptional Bind(Func> binder)
=> Match(
exception: ex => (Exceptional)F.ExceptionThrown(ex),
success: binder);
public bool Equals(Exceptional other) => _either.Equals(other._either);
public override bool Equals(object? obj) => obj is Exceptional other && Equals(other);
public override int GetHashCode() => _either.GetHashCode();
public override string ToString() => Match(
exception: ex => $"ExceptionThrown({ex.Message})",
success: value => $"Success({value})");
public static bool operator ==(Exceptional left, Exceptional right) => left.Equals(right);
public static bool operator !=(Exceptional left, Exceptional right) => !left.Equals(right);
}
}