如何判断LanguageExt.Core的Result<T>是否出错以触发Polly重试
}
```csharp private async Task<Result<Unit>> ConnectAsync(Uri uri) { if (_ws is not null) { return new Result<Unit>(new InvalidOperationException("The websocket client is already connected")); } var ws = Options.ClientFactory(); try { using var connectTimeout = new CancellationTokenSource(Options.Timeout); await ws.ConnectAsync(uri, connectTimeout.Token).ConfigureAwait(false); } catch { ws.Dispose(); return new Result<Unit>(new InvalidOperationException("Failed to connect to the endpoint")); } await _connectedEvent.InvokeAsync(new ConnectedEventArgs(uri)); _ws = ws; IsRunning = true; return Unit.Default; }
解决方案
1. 用IfFailThrow()直接抛出异常
LanguageExt的Result<T>自带IfFailThrow()扩展方法,一旦Result处于失败状态,就会自动抛出内部的异常,直接触发Polly的重试逻辑,写法最简洁:
private async Task RunAsync(Uri uri) { var result = await ConnectAsync(uri); // 失败时直接抛出异常,无需额外判断 result.IfFailThrow(); // 后续正常业务逻辑 ... }
2. 用Match做日志后再抛出
如果需要先记录错误日志再抛出异常,用Match方法是更贴合LanguageExt函数式设计的方式,它能分别处理成功和失败分支:
private async Task RunAsync(Uri uri) { var result = await ConnectAsync(uri); result.Match( _ => { /* 成功时的逻辑,这里不需要可以留空 */ }, ex => { _logger.LogError(ex, "连接端点出错"); throw ex; // 抛出异常触发Polly重试 } ); ... }
3. 优化ConnectAsync的Result创建方式
你当前手动new Result<Unit>(异常)的写法不够规范,LanguageExt提供了静态方法来创建Result,更符合函数式风格:
- 成功结果:直接返回
Unit.Default(LanguageExt支持隐式转换为Result<Unit>.Success) - 失败结果:用
Result<Unit>.Fail(异常)创建
优化后的ConnectAsync代码:
private async Task<Result<Unit>> ConnectAsync(Uri uri) { if (_ws is not null) { return Result<Unit>.Fail(new InvalidOperationException("WebSocket客户端已连接")); } var ws = Options.ClientFactory(); try { using var connectTimeout = new CancellationTokenSource(Options.Timeout); await ws.ConnectAsync(uri, connectTimeout.Token).ConfigureAwait(false); } catch { ws.Dispose(); return Result<Unit>.Fail(new InvalidOperationException("连接端点失败")); } await _connectedEvent.InvokeAsync(new ConnectedEventArgs(uri)); _ws = ws; IsRunning = true; return Unit.Default; }
关于无法访问result.Exception的原因
LanguageExt把Result<T>的Exception设为内部属性,是为了强制开发者使用它提供的函数式API(比如Match、IfFail系列方法)来处理结果,避免直接操作内部状态,这是函数式编程强调“纯操作”、避免副作用的设计思路。
内容的提问来源于stack exchange,提问作者Hulkstance
相关产品推荐
相关产品推荐

