从对 Invoke 的调用中获取正确的异常类型(反射)

发布于 2024-11-24 21:36:26 字数 794 浏览 1 评论 0 原文

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

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 的事实?

In our integration project we are dynamically delegating to a series of specific Processor objects using Reflection.

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

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

Now, in certain situations, one of the processors needs to throw a specific Exception, in this case when he doesn't find a file in the expected location.

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

Our processor wants to check on this exception to determine whether processing needs to be retried or aborted (based on a time-based mechanism, which is not relevant here).

catch(ResourceNotFoundException ex)
{
   // do stuff
}

The problem is that the invoke apparently "swallows" the specific ResourceNotFoundException and rethrows a System.Exception saying "Exception has been thrown by the target of an invocation."

Is there any way of preserving the fact through Reflection that a ResourceNotFoundException was actually thrown and not an Exception?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

各空 2024-12-01 21:36:26

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

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;
}

但请注意,这将替换内部异常的堆栈跟踪。 这个答案是如此

MethodBase.Invoke(Object, Object[]) wraps any exception thrown by the invoked method in a TargetInvocationException. You can access the inner exception and either process it directly, or rethrow it to be processed further up the stack as in the following example:

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;
}

Note however that this will replace the inner exception's stack trace. A (technically unsupported) way of preserving the stack trace is described in this answer on SO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文