如何在C#中从字符串获取异常类型并匹配对应错误处理策略?
刚好我之前处理过类似的Polly动态策略问题,给你一步步拆解解决:
如何从字符串异常名称获取类型并动态应用Polly策略?
你的核心问题有两个:一是从短字符串异常名(比如TimeoutException)正确获取对应的Type对象,二是根据配置动态生成Polly策略。下面逐个解决:
1. 解决从字符串获取异常类型的问题
你当前用Type.GetType(exceptionName)大概率失效,因为这个方法需要完整的类型全名(包含命名空间),比如System.TimeoutException,但你的JSON里只存了短名称。
可以写一个辅助方法,自动查找匹配的异常类型:
private Type GetExceptionType(string exceptionName) { // 先尝试直接获取(如果传入的是完整类型名) var targetType = Type.GetType(exceptionName); if (targetType != null) return targetType; // 遍历所有已加载的程序集,找名称匹配且继承自Exception的类型 foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { targetType = assembly.GetTypes() .FirstOrDefault(t => t.Name.Equals(exceptionName, StringComparison.OrdinalIgnoreCase) && typeof(Exception).IsAssignableFrom(t)); if (targetType != null) return targetType; } throw new ArgumentException($"未找到名为「{exceptionName}」的异常类型"); }
这个方法会先尝试直接匹配完整类型名,找不到就遍历所有已加载程序集,精准定位符合条件的异常类型。
2. 动态生成Polly策略
Polly的Handle<T>是泛型方法,没法直接用字符串类型调用,我们可以用非泛型的Handle方法+类型判断的方式来实现动态匹配,再结合你的配置生成对应策略。
完整重构后的代码
首先确保你的配置模型类正确:
public class RootObject { public List<ExceptionMapper> ExceptionMappers { get; set; } } public class ExceptionMapper { public string ExceptionName { get; set; } public string ExceptionType { get; set; } public string Policy { get; set; } public string WaitType { get; set; } }
然后修改Execute方法,实现动态策略逻辑:
public void Execute(Action action, string exceptionName) { var filePath = @"appsetting.json"; var exceptionMapperJson = File.ReadAllText(filePath); var rootNode = JsonConvert.DeserializeObject<RootObject>(exceptionMapperJson); var exceptionNode = rootNode.ExceptionMappers.FirstOrDefault(e => e.ExceptionName.Equals(exceptionName, StringComparison.OrdinalIgnoreCase)); // 无匹配配置时执行空策略 if (exceptionNode == null) { Policy.NoOp().Execute(action); return; } // 获取目标异常类型 var targetExceptionType = GetExceptionType(exceptionNode.ExceptionName); ISyncPolicy policy = null; // 根据配置生成对应策略 switch (exceptionNode.Policy) { case "WaitAndRetry": var retryCount = 3; // 建议把重试次数也放到JSON配置里 if (exceptionNode.WaitType == "Linear") { policy = Policy .Handle(ex => ex.GetType() == targetExceptionType) .WaitAndRetry(retryCount, retryAttempt => TimeSpan.FromSeconds(retryAttempt)); } // 可扩展其他等待策略,比如指数退避 break; case "CircuitBreaker": policy = Policy .Handle(ex => ex.GetType() == targetExceptionType) .CircuitBreaker(2, TimeSpan.FromSeconds(30)); // 熔断阈值和时长也建议配置化 break; case "LogOnly": // LogOnly策略:捕获异常后记录日志,再重新抛出 policy = Policy .Handle(ex => ex.GetType() == targetExceptionType) .Retry(0, (ex, _) => { // 这里替换成你的日志逻辑,比如: // Logger.LogError(ex, "捕获到需仅记录日志的异常"); }); break; default: policy = Policy.NoOp(); break; } // 用生成的策略执行目标Action policy.Execute(action); }
额外优化建议
- 把重试次数、熔断阈值、等待时长这些参数也放到JSON配置里,让策略完全可配置
- 缓存已获取的异常类型,避免每次都遍历程序集,提升性能
- 给找不到类型的情况添加 fallback 逻辑,比如默认执行空策略
内容的提问来源于stack exchange,提问作者Developer
相关产品推荐
相关产品推荐

