如何通过ConfigurePrimaryHttpMessageHandler/AddPolicyHandler重试无法引用的内部密封异常?
如何对内部密封异常执行Polly重试?
问题背景
想要通过Polly的AddPolicyHandler实现包含内部密封异常的重试逻辑,理想代码如下:
.AddPolicyHandler(HttpPolicyExtensions .HandleTransientHttpError() // 捕获408、5xx状态码 .Or<SocksException>() .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt))));
但SocksException是内部密封类,定义如下,无法直接在代码中引用:
internal sealed class SocksException : IOException { public SocksException(string message) : base(message) { } public SocksException(string message, Exception innerException) : base(message, innerException) { } }
尝试捕获IOException未生效,需要其他解决方案。
解决方案
1. 通过完整类型名称匹配(推荐)
利用反射获取异常的完整类型名称(命名空间+类名),在Polly的Handle方法中通过自定义判断逻辑精准捕获该异常:
.AddPolicyHandler(HttpPolicyExtensions .HandleTransientHttpError() .Handle(ex => // 替换为SocksException实际的完整命名空间 ex.GetType().FullName == "YourNamespace.SocksException" && ex is IOException) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt))));
这种方式直接匹配目标异常类型,不会误捕获其他IOException子类,可靠性较高。
2. 结合异常特征判断(备选)
如果无法确定完整类型名称,可以通过异常的消息内容、内部异常等特征辅助判断(注意:消息内容可能随库版本变化,可靠性较低):
.AddPolicyHandler(HttpPolicyExtensions .HandleTransientHttpError() .Handle(ex => ex is IOException && ex.Message.Contains("SOCKS") // 假设异常消息包含相关关键词 ) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt))));
3. 处理包装在内部的异常
如果SocksException被包装在其他异常(如AggregateException)内部,需要结合OrInner方法捕获深层异常:
.AddPolicyHandler(HttpPolicyExtensions .HandleTransientHttpError() .Handle(ex => ex.GetType().FullName == "YourNamespace.SocksException") .OrInner(ex => ex.GetType().FullName == "YourNamespace.SocksException") .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt))));
补充说明
若之前捕获IOException未生效,大概率是因为抛出的异常被包装在其他异常类型中,或者存在其他过滤逻辑导致未触发重试。此时可以通过调试查看异常的完整调用栈,确认异常的实际传递路径,再调整捕获逻辑。
内容的提问来源于stack exchange,提问作者Steji
相关产品推荐
相关产品推荐

