You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反射调用SetValue时丢失原始异常,如何获取原异常用于日志记录?

问题:反射调用SetValue时无法捕获属性Setter的原始异常

使用反射通过PropertyInfo.SetValue()给对象属性批量赋值时,属性setter抛出的原始异常(如示例中的ArgumentException)会被.NET包装为TargetInvocationException,导致日志仅显示通用错误信息“Exception has been thrown by the target of an invocation.”,无法获取原始异常的具体详情。

原代码片段

try
{
    PropertyInfo piInstance = MBtype.GetProperty(columnlist[intColumn]);
    piInstance.SetValue(newMailbox, CurrentRow[intColumn]);
}
catch (Exception ex)
{
    HelpFunc.writeToLog($"Error: '{ex.Message}'", "Error");
}

Setter中的原始异常代码

throw new ArgumentException($"{value} must be valid email address", value);

解决方案

反射调用的SetValue()方法会将目标方法抛出的所有异常包装到TargetInvocationException的InnerException属性中,因此只需提取该属性即可获取原始异常信息。以下是两种可行的处理方式:

方式1:直接捕获TargetInvocationException

优先捕获反射特有的包装异常,直接提取原始异常:

try
{
    PropertyInfo piInstance = MBtype.GetProperty(columnlist[intColumn]);
    piInstance.SetValue(newMailbox, CurrentRow[intColumn]);
}
catch (TargetInvocationException tiex)
{
    // 优先取InnerException,为空则用自身
    Exception originalException = tiex.InnerException ?? tiex;
    // 记录原始异常的消息
    HelpFunc.writeToLog($"Error: '{originalException.Message}'", "Error");
    // 可选:记录完整异常信息(含栈跟踪)便于排查
    // HelpFunc.writeToLog($"Full error details:\n{originalException.ToString()}", "Error");
}
catch (Exception ex)
{
    // 处理其他非反射引发的异常
    HelpFunc.writeToLog($"Error: '{ex.Message}'", "Error");
}

方式2:递归获取根异常

如果存在多层异常包装的情况,可以通过辅助方法递归获取最内层的原始异常:

// 辅助方法:获取最内层的原始异常
private static Exception GetRootException(Exception ex)
{
    while (ex.InnerException != null)
    {
        ex = ex.InnerException;
    }
    return ex;
}

// 使用示例
try
{
    PropertyInfo piInstance = MBtype.GetProperty(columnlist[intColumn]);
    piInstance.SetValue(newMailbox, CurrentRow[intColumn]);
}
catch (Exception ex)
{
    Exception rootException = GetRootException(ex);
    HelpFunc.writeToLog($"Error: '{rootException.Message}'", "Error");
}

说明

  • TargetInvocationException是.NET反射机制专门用于包装目标方法异常的类型,其InnerException必然包含原始抛出的异常(除非原始异常本身为空)。
  • 日志记录时建议保留完整的异常信息(如ToString()的结果),这包含了异常类型、消息、栈跟踪等关键信息,能大幅提升问题排查效率。

内容的提问来源于stack exchange,提问作者user3844416

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 12:22:46