1

次のコードがあります。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        try
        {
            this.CheckValue(true); // call method
        }
        catch(Exception ex)
        {
            // how to get here name of last called method
        }
    }

    public int CheckValue(bool sender)
    {
        var qwe = int.Parse("qwe"); // invoke an exception

        return 0;
    }
}

最後に呼び出されたメソッド (この場合は「CheckValue」) の「catch ブロック」名を取得する必要がありますが、呼び出されたメソッドが「StringToNumber」であることを返します。

StackTrace を使用して取得しようとしています。

stackTrace.GetFrame(1).GetMethod().Name; -> "Main"
MethodBase.GetCurrentMethod(); -> "Void .ctor()"
ex.TargetSite.Name; -> "StringToNumber"

これを行うことは可能ですか?

4

3 に答える 3

3

簡潔な答え:

はい、できます!!!


ここでの秘訣は、目的のクラスの最後のフレームを取得することです。そうしないと、mscorlib アセンブリのメソッドが取得されます。だからここに行きます:

public static string GetLastCalledMethod<T>(this Exception ex)
{
    var stackTrace = new System.Diagnostics.StackTrace(ex);
    var lastFrame = stackTrace.GetFrames().FirstOrDefault(frame => frame.GetMethod().DeclaringType.FullName == typeof(T).FullName);

    string methodName = string.Empty;
    if (lastFrame != null)
        methodName = lastFrame.GetMethod().Name;

    return methodName;
}
于 2012-08-03T13:13:58.180 に答える
1

簡潔な答え:

できません。


長い答え:

本当にそれを行う必要がある場合は、追跡するすべてのメソッドでログ コードを実行する必要があります。

グローバル変数 (ugh) を作成しMethodInfoて、最後に呼び出されたメソッドで を格納し、すべてのメソッド内で に設定できMethodBase.GetCurrentMethod()ます。その後、いつでもその変数を調べて、最後に設定されたメソッドを確認できます。


あなたの場合、おそらく例外がスローされたメソッドを特定しようとしています。TargetSite階層内の最下位のメソッドを返す を見ていますが、現在のメソッドのすぐ下にあるメソッドが必要なようです。単純に調べるだけException.StackTraceでは十分な情報が得られない場合は、 から情報を解析しStackTrace、リフレクションを使用してMethodInfo. 通常はこれStackTraceで十分です。

トップレベルのメソッドで新しい例外をスローできる場合もあるため、新しい例外TargetSiteから取得できます。

概要:

Exception.StackTrace十分な情報が提供されない場合は、次のいずれかを行う必要があります。

  • チェックする各メソッドでログ コードを実行します。
  • から取得できる情報を解析しますException
  • 元の例外に設定された新しい例外をスローするように、例外スロー スキームを変更しInnerExceptionます。
于 2012-08-03T12:56:55.953 に答える
0

なぜこれをしたいのかわかりません..これは予想される動作であるためです。例外のサイトは、int.Parse() 呼び出し内で表示されているものです。

そうは言っても..本当にこれをやりたい場合は、try..catchをCheckValueでラップし、そこから例外を再スローする必要がありますが、コールスタックを壊す方法で..次のように:

public int CheckValue(bool sender) {
    try {
        var qwe = int.Parse("qwe"); // invoke an exception

        return 0;
    }
    catch (Exception ex) {
        throw ex; // this breaks the call stack and re-throws the exception from here..
    }
}

次に、ex.TargetSite.Name == "CheckValue". なぜこれを行う必要があるのか​​ 、まだわかりません..スタックトレースは、失敗後にすべてが巻き戻された場所を実際に示します。

于 2012-08-03T12:49:01.180 に答える