gpt4 book ai didi

c# - 如何在不丢失堆栈跟踪的情况下重新抛出 TargetInvocationException 的内部异常

转载 作者:IT王子 更新时间:2023-10-29 04:38:20 25 4
gpt4 key购买 nike

我有许多使用 Delegate.DynamicInvoke 调用的方法。其中一些方法进行数据库调用,我希望能够捕获 SqlException 而不是捕获 TargetInvocationException 并搜索其内部以找出实际出错的地方。

我正在使用这个方法重新抛出,但它清除了堆栈跟踪:

 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 方法是我在另一篇文章中修复的扩展方法(我不知道它实际上做了什么)。但是,这似乎也没有保留痕迹:

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

最佳答案

如果你只是想重新抛出一个保留其堆栈跟踪的内部异常,你可以用这样的方法来完成:

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)。

但是请注意,此技术在技术上不受支持。希望微软将来会为此添加一个官方 API。一个建议has been opened在 Microsoft Connect 上投票。

更新:官方 API 已添加到 .NET 4.5:ExceptionDispatchInfo .

关于c# - 如何在不丢失堆栈跟踪的情况下重新抛出 TargetInvocationException 的内部异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4555599/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com