【问题标题】:Getting the correct Exception type out of a call to Invoke (reflection)从调用调用中获取正确的异常类型(反射)
【发布时间】:2011-10-07 13:03:30
【问题描述】:

在我们的集成项目中,我们使用反射动态地委托给一系列特定的处理器对象。

var genericType = typeof(IMessageProcessor<>).MakeGenericType(parseResponse.DomainMessage.GetType());

var miProcessMessage = genericType.GetMethod("ProcessMessage");
miProcessMessage.Invoke(processor, new object[] { parseResponse.DomainMessage });

现在,在某些情况下,其中一个处理器需要抛出一个特定的异常,在这种情况下,当他在预期位置找不到文件时。

throw new ResourceNotFoundException(string.Format("Could not find file {0}", filePath));

我们的处理器想要检查此异常以确定是否需要重试或中止处理(基于基于时间的机制,此处不相关)。

catch(ResourceNotFoundException ex)
{
   // do stuff
}

问题在于调用显然“吞下了”特定的 ResourceNotFoundException 并重新抛出 System.Exception 说“调用的目标已抛出异常。”

有没有什么方法可以通过反射来保留实际抛出 ResourceNotFoundException 而不是 Exception 的事实?

【问题讨论】:

    标签: .net reflection exception-handling invoke


    【解决方案1】:

    MethodBase.Invoke(Object, Object[]) 将调用方法抛出的任何异常包装在TargetInvocationException 中。您可以访问内部异常并直接对其进行处理,或者将其重新抛出以在堆栈中进一步处理,如下例所示:

    var genericType = typeof(IMessageProcessor<>).MakeGenericType(parseResponse.DomainMessage.GetType());
    var miProcessMessage = genericType.GetMethod("ProcessMessage");
    try {
        miProcessMessage.Invoke(processor, new object[] { parseResponse.DomainMessage });
    catch (TargetInvocationException ex)
    {
        throw ex.InnerException;
    }
    

    但是请注意,这将替换内部异常的堆栈跟踪。 this answer on SO 中描述了一种(技术上不受支持的)保留堆栈跟踪的方法。

    【讨论】:

    • 这也是我发现的,是的。有趣的是它适用于内置的异常类型,例如 SqlException 或 TransactionException,它们没有被包装,可以直接在它们自己的异常块中处理。对于其他人,我们需要查看 InnerException 类型。
    猜你喜欢
    • 2021-04-24
    • 2011-09-15
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多