20

を使用して呼び出している多くのメソッドがありますDelegate.DynamicInvoke。これらのメソッドのいくつかはデータベース呼び出しを行います。私は、 a をキャッチし、 をキャッチせSqlExceptionTargetInvocationExceptionにその内部を調べて、実際に何が問題なのかを見つける機能を持ちたいと考えています。

このメソッドを使用して再スローしましたが、スタック トレースがクリアされます。

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

3 に答える 3

29

スタック トレースを保持したまま内部例外を再スローするだけの場合は、次のようなメソッドを使用して実行できます。

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 は必要ありません)。

ただし、この手法は技術的にサポートされていないことに注意してください。うまくいけば、Microsoft は将来、このための公式 API を追加します。投票したい場合は、Microsoft Connect で提案が開かれています。

更新:公式 API が .NET 4.5: に追加されましたExceptionDispatchInfo

于 2010-12-29T19:30:37.717 に答える
2

.NET が元の例外を単に通過させるのではなく、TargetInvocationException で例外をラップする理由を覚えておく必要があります。それには本当に正当な理由があります。例外の本当の理由がどこから来たのかは明らかではありません。DynamicInvoke() 呼び出しが中断されたためですか? おそらく、正しい引数が渡されたことを保証するためにコンパイラーができることは何もありません。それとも、呼び出されたターゲット メソッドがすべて単独でスローしたのでしょうか?

例外の本当の理由を判断するには、両方を知る必要があります。TargetInvocationException を意図的に非表示にすると、実際に DynamicInvoke() 呼び出しの問題である場合、問題の原因を診断するのが難しくなります。これは避けてください。

于 2010-12-29T16:24:11.147 に答える
0

IIRC では例外を完全に保存することはできませんが、スタック トレースはある程度反映して保存できます。これを行う方法を説明するブログ投稿は次のとおりです。http://iridescence.no/post/Preserving-Stack-Traces-When-Re-Throwing-Inner-Exceptions.aspx

于 2010-12-29T16:13:44.003 に答える