11

Webアプリケーションで例外を処理するための次のコードがあります。

application.Response.Clear();
application.Response.Status = Constants.HttpServerError;
application.Response.TrySkipIisCustomErrors = true;

LogApplicationException(application.Response, exception);
try
{
    WriteViewResponse(exception);
}
// now we're in trouble. lets be as graceful as possible.
catch (Exception exceptionWritingView)
{
    // Exception wrapper = ??
    WriteGracefulResponse(exceptionWritingView);
}
finally
{
    application.Server.ClearError();
}

ここでの問題は、応答をとしてレンダリングしようとしているときに例外が発生した場合、元の例外を(とにかく)ViewResult「抑制」し、エラーがスローされた原因を表示するだけであるということです。ViewViewResult

exception両方を取り、両方でexceptionWritingView1つの例外を作成exceptionWritingViewし、上部に配置します。

これは:

exceptionWritingView
    -> inner exceptions of exceptionWritingView
            -> original exception that raised the unhandled exception handler
                       -> its inner exceptions

しかし、オブジェクトにInnerExceptionプロパティを設定することはできません。exceptionでは、どうすればこれを達成できますか?

「最高の」状態で、Exceptionを使用して新しいものを作成することはできますが、プラスnew Exception(exceptionWritingView.Message, exception)の一部を失うことになり、持っていた可能性のあるものを失うことになります。StackTraceInnerExceptionexceptionWritingView

ここでの唯一の方法は反射ですか?振り返ってそれをするのはそれほど恐ろしいことでしょうか?

4

4 に答える 4

20

System.AggregateExceptionを使用できます。

例:

WriteGracefulResponse(new AggregateException(new Exception[]
{
    exceptionWritingView,
    originalUnhandledException
}));
于 2012-08-12T06:40:06.913 に答える
0

なぜ物事を複雑にするのですか?exceptionパラメータとしてWriteGracefulResponseメソッドに渡してみませんか?

...
// now we're in trouble. lets be as graceful as possible. 
catch (Exception exceptionWritingView) 
{ 
   // Exception wrapper = ?? 
   WriteGracefulResponse(exception, exceptionWritingView); 
} 

exceptionWritingViewまた、で終わるものに名前を変更する必要exceptionがあります。これは、これがビューであると考える読者を混乱させます。

于 2012-08-12T06:47:48.547 に答える
0

セッターを介して内部例外を設定するのではなく、コンストラクターを介して設定します。

application.Response.Clear();
application.Response.Status = Constants.HttpServerError;
application.Response.TrySkipIisCustomErrors = true;

LogApplicationException(application.Response, exception);
try
{
    WriteViewResponse(exception);
}
// now we're in trouble. lets be as graceful as possible.
catch (Exception exceptionWritingView)
{
    // Example on how to nest exceptions.
    throw MyException("Error message", exceptionWritingView);
}
finally
{
    application.Server.ClearError();
}

スタックトレースは内部例外に保存されます。

于 2012-08-12T04:31:21.030 に答える
0

あなたが述べたように、最大​​の問題は、例外がゲッターのみを提供し、これがあなたができることを制限することです。これを解決するには、Exceptionから継承して、そのプロパティを設定可能にすることができます。私のサンプルクラスでは、FlexibleExceptionを初期化できます。これは、基本的にそのコピーを作成する通常の例外を介して再発しますが、コピーは設定可能です。次に、前の例外を追加するために、最後を見つけてそれに取り組むまではしごを下って移動し、2つの例外を連結します。私はこのようなものを使う必要がなかったので、これは私が書いたものであり、いくつかのバグがあるかもしれませんが、それはあなたがやろうとしていることを達成すると信じています。

application.Response.Clear();
application.Response.Status = Constants.HttpServerError;
application.Response.TrySkipIisCustomErrors = true;

LogApplicationException(application.Response, exception);
try
{
    WriteViewResponse(exception);
}

catch (Exception exceptionWritingView)
{
    FlexibleException lastException = new FlexibleException(exceptionWritingView);
    lastException.AddPreviousException(exception);
    WriteGracefulResponse(lastException);
}
finally
{
    application.Server.ClearError();
}

public class FlexibleException : Exception
{
    public FlexibleException(Exception e)
    {
        this.InnerException = e.InnerException != null ? new FlexibleException(e.InnerException) : null;
        this.StackTrace = e.StackTrace;
    }

    public FlexibleException InnerException { get; set; }

    public string StackTrace { get; set; }

    public void AddPreviousException(Exception e)
    {
            FlexibleException prevException = new FlexibleException(e);
        FlexibleException nextException = this;

        while (true)
        {
            if (nextException.InnerException != null)
            {
               nextException = nextException.InnerException;
               continue;
            }
            else
            {
               nextException = prevException;
               break;
            }
        }
    }
}

編集:継承によってInnerExceptionまたはStackTraceにセッターを追加することはできませんが、別のセッタープロパティWritableStackTraceを追加し、StackTraceをオーバーライドしてその値を返すことができます(技術的には設定可能にします)。

派生されたExceptionクラスを作成する別の方法は、AddPreviousExceptionと非常によく似た関数を作成することです。ただし、例外オブジェクトにドリルダウンして再作成し、コンストラクターに連結する例外を渡してから、作業を進めます。各例外を飲み込みます。

于 2012-08-12T12:13:00.583 に答える