如何重新抛出TargetInvocationException的内部异常,而不会丢失堆栈跟踪 [英] How to rethrow the inner exception of a TargetInvocationException without losing the stack trace
问题描述
我有许多方法使用 Delegate.DynamicInvoke
调用。这些方法中的一些使数据库调用,我想有能力捕获一个 SqlException
,而不是捕获 TargetInvocationException
并且通过它的内部寻找发现实际出错了。
I have many methods which are calling using Delegate.DynamicInvoke
. Some of these methods make database calls and I would like to have the ability to catch a SqlException
and not catch the TargetInvocationException
and hunt through its inners to find what's actually gone wrong.
我使用这种方法来重新抛出,但它清除堆栈跟踪:
I was using this method to rethrow but it clears the stack trace:
try
{
return myDelegate.DynamicInvoke(args);
}
catch(TargetInvocationException ex)
{
Func<TargetInvocationException, Exception> getInner = null;
getInner =
delegate(TargetInvocationException e)
{
if (e.InnerException is TargetInvocationException)
return getInner((TargetInvocationException) e.InnerException);
return e.InnerException;
};
Exception inner = getInner(ex);
inner.PreserveStackTrace();
throw inner;
}
PreserveStackTrace
是一个扩展方法我修复了感谢另一篇文章(我不知道它实际上是什么)。但是,这并不会保留跟踪:
The PreserveStackTrace
method is an extension method I fixed up thanks to another post (I don't know what it actually does). However, this doesn't appear to preserve the trace either:
public static void PreserveStackTrace(this Exception e)
{
var ctx = new StreamingContext(StreamingContextStates.CrossAppDomain);
var mgr = new ObjectManager(null, ctx);
var si = new SerializationInfo(e.GetType(), new FormatterConverter());
e.GetObjectData(si, ctx);
mgr.RegisterObject(e, 1, si);
mgr.DoFixups();
}
推荐答案
- 抛出一个保留其堆栈跟踪的内部异常,你可以使用这样的方法:
If you just want to re-throw an inner exception preserving its stack trace, you can do it with a method like this:
public static void Rethrow(this Exception ex)
{
typeof(Exception).GetMethod("PrepForRemoting",
BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(ex, new object[0]);
throw ex;
}
这种技术由Rx使用(并被他们作为扩展方法公开 Exception.PrepareForRethrow
),也由Async CTP通过其自动展开系统(没有公开的API)使用。
This technique is used by Rx (and is exposed by them as an extension method Exception.PrepareForRethrow
) and is also used by the Async CTP by its automatic-unwrapping system (without a publicly-exposed API).
但是,请注意,这种技术在技术上不受支持。希望Microsoft将来会为此添加官方API。建议已被打开一个>在Microsoft Connect上,如果你想投票。
Note, however, that this technique is technically unsupported. Hopefully Microsoft will add an official API for this in the future. A suggestion has been opened on Microsoft Connect if you would like to vote for it.
更新:已将官方API添加到.NET 4.5: a href =http://msdn.microsoft.com/en-us/library/system.runtime.exceptionservices.exceptiondispatchinfo%28v=vs.110%29.aspx =noreferrer> ExceptionDispatchInfo
。
Update: An official API has been added to .NET 4.5: ExceptionDispatchInfo
.
这篇关于如何重新抛出TargetInvocationException的内部异常,而不会丢失堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!