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

我需要输入最后调用方法的“catch block”名称(在本例中为“CheckValue”),但它返回调用的方法是“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)来存储 aMethodInfo与最后调用的方法,并在每个方法中,将其设置为MethodBase.GetCurrentMethod(). 然后,无论何时,您都可以检查该变量以查看最后设置它的方法。


在您的情况下,您可能正在尝试确定抛出异常的方法。您正在查看TargetSite,它返回层次结构中最低的方法,而您似乎想要紧挨当前方法下方的方法。如果简单地检查Exception.StackTrace不能提供足够的信息,您也许可以从中解析出信息StackTrace并使用反射来获取MethodInfo. 通常,这StackTrace已经足够好了。

您还可以在顶级方法中抛出一个新异常,以便从新方法中获取TargetSite

概括:

如果Exception.StackTrace没有提供足够的信息,那么您将不得不:

  • 在您要检查的每种方法中执行日志记录代码。
  • 解析出你可以从Exception.
  • 更改异常抛出方案以抛出一个InnerException设置为原始异常的新异常。
于 2012-08-03T12:56:55.953 回答
0

我不知道你为什么要这样做..因为这是预期的行为。异常的站点是您在 int.Parse() 调用中显示的内容。

话虽这么说..如果你真的想这样做,你需要在CheckValue中包装一个try..catch,然后从那里重新抛出异常,但是以一种破坏调用堆栈的方式......就像这样:

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 回答