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); } }