如何重新抛出一个TargetInvocationException的内部异常不失堆栈跟踪 [英] How to rethrow the inner exception of a TargetInvocationException without losing the stack trace

查看:339
本文介绍了如何重新抛出一个TargetInvocationException的内部异常不失堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 Delegate.DynamicInvoke 调用许多方法。有些方法使数据库调用,我想必须抓住能力的SQLException ,而不是赶 TargetInvocationException 猎通过其胆找到什么真正出了问题。

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

 尝试
 {
      返回myDelegate.DynamicInvoke(参数);
 }
 赶上(TargetInvocationException前)
 {
     FUNC< TargetInvocationException,异常> getInner = NULL;
     getInner =
        委托(TargetInvocationException E)
        {
        如果(e.InnerException是TargetInvocationException)
            返回getInner((TargetInvocationException)e.InnerException);         返回e.InnerException;
        };     例外内= getInner(除息);
     。内preserveStackTrace();
     扔内;
 }

preserveStackTrace 方法是一个扩展方法我搞掂感谢另一篇文章(我不知道它实际上做)。然而,这不会出现preserve跟踪之一:

 公共静态无效preserveStackTrace(这个例外五)
{
    VAR CTX =新的StreamingContext(StreamingContextStates.CrossAppDomain);
    VAR经理=新的ObjectManager(NULL,CTX);
    变种SI =新的SerializationInfo(e.GetType(),新FormatterConverter());    e.GetObjectData(SI,CTX);
    mgr.RegisterObject(E,1,SI);
    mgr.DoFixups();
}


解决方案

如果你只是想重新引发内部异常preserving它的堆栈跟踪,你可以用这样的方法做到这一点:

 公共静态无效的重新抛出(此异常前)
{
  typeof运算(例外).GetMethod(prepForRemoting
      BindingFlags.NonPublic可| BindingFlags.Instance)
      .Invoke(例如,新的对象[0]​​);
  扔恩;
}

此技术被用来以Rx(并且由他们暴露为扩展方法异常。prepareForRethrow ),并还用于通过异步CTP通过其自动-unwrapping系统(没有公开暴露的API)。

请注意,但是,这种技术在技术上是不支持的。希望微软将在未来增加一个官方的API这一点。有人建议<一href=\"https://connect.microsoft.com/VisualStudio/feedback/details/633822/allow-$p$pserving-stack-traces-when-rethrowing-exceptions\">has被打开微软连接,如果你想为它投票。

更新:一个官方的API已经被添加到.NET 4.5:<一href=\"http://msdn.microsoft.com/en-us/library/system.runtime.exceptionservices.exceptiondispatchinfo%28v=vs.110%29.aspx\"><$c$c>ExceptionDispatchInfo.

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

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

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

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.

Update: An official API has been added to .NET 4.5: ExceptionDispatchInfo.

这篇关于如何重新抛出一个TargetInvocationException的内部异常不失堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆