70

私は次のコードを持っています:

catch(Exception ex)
{
    throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}

残念ながら、これは例外を飲み込むだけです。これを修正するには、次のようにします。

catch(Exception ex)
{
    throw;
}

ただし、イベントのログ記録に役立つカスタムメッセージを含めたいと思います。

情報を失うことなく、このメッセージを例外に追加するにはどうすればよいですか?(スタックトレース/デバッグシンボルなど)

4

4 に答える 4

97

ユーザーが読み取り可能なメッセージや、エラーの追跡には役立つがエンドユーザーには役立たない特定の詳細など、元の例外に情報を追加する必要がある場合は、次を利用できます。キー/値ペアディクショナリであるExceptionのDataプロパティ。

実行中のレポートや処理中のファイルなどの情報を記録して、エラー発生時に何が起こっていたかを操作で判断できるようにするために、これを幅広く使用しています。ユーザーは障害の原因を直接処理しているため、この詳細は必要ありません。

これを使用して、ユーザーにとって意味のあるプレーンテキストメッセージを渡すこともできます。唯一の問題は、データを抽出して消費者に役立つようにするために、ロギングフレームワークまたはエンドユーザーインターフェイスで追加の作業を実行する必要があることです。

たとえば、次のことができます。

catch (Exception ex)
{
    ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file.");
    throw;
}

次に、クライアント側のコードで、UserMessageが存在するかどうかをテストし、存在する場合は、例外の代わりにそれをユーザーに提示できます。

catch (Exception ex)
{
    if (ex.Data.Contains("UserMessage"))
    {
        MessageBox.Show(ex.Data["UserMessage"].ToString());
    }
    else
    {
        MessageBox.Show(ex.Message);
    }
}
于 2013-01-19T01:28:02.697 に答える
17

その元の例外はまだあります。

例外ロギングを行う場合、受け取る例外は、メッセージで作成したFatalExceptionになります。元の例外はにありex.InnerExceptionます。すべてのスタックトレース情報などを取得するために、nullになるまでInnerExceptionを循環し続けることができます。

于 2013-01-19T01:00:16.050 に答える
2

要するに、しないでください。

少し考えてみれば、これを回避する方法が見つかると思いますが、これには強く注意します。これは、.NETの例外の元の設計に反します。例外は、ロギングを支援するためだけにあるのではなく、アプリケーション障害の元の原因に関する情報を提供します。

最初のオプションを使用すると、元の例外のスタックトレースが維持されますが、別の例外でラップすることで追加情報を提供できるため、一般的に推奨されます。私自身のコードでは、例外をログに記録するたびに、ログ関数がInnerExceptionプロパティを介して再帰し、エラーに関して可能なすべての有用な情報を見つけます。

于 2013-01-19T01:07:13.013 に答える
0

誰かが良い答えを必要とする場合に備えて。重要なのは、AppDomain.CurrentDomain.FirstChanceExceptionを使用することです

IDisposableを使用してカスタムオブジェクトを作成し、すべての情報をその中に入れることができます。そして、例外が発生した場合、FirstChanceExceptionハンドラーはその情報を取得し、Exception.Dataにデータを入力します。

ローカルスレッドストレージを使用して、スレッドセーフにします。次に、それをキャッチするコードがデータを取得してログに記録します。

例:

using(MyCustomMessage.EnterToLocalStorage("Info for logging"") ) 
{ 
...code 
...exception thrown
.... FirstChanceException examines local thread storage and get's "info for logging" and puts into Exception.Data. 
} 
//Dispose is called and all messages that were put into LocalStorage are removed. 
//So if exception was not thrown before then it like nothing happened.

良い例としてGoogleAsyncDiagnosticStack。https://github.com/StephenCleary/AsyncDiagnostics/blob/master/src/Nito.AsyncEx.AsyncDiagnostics/AsyncDiagnosticStack.cs

于 2019-10-05T04:56:42.717 に答える