获取上次调用方法的名称

时间:2012-08-03 10:40:23

标签: c# c#-4.0 methods

我有以下代码:

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"

可以这样做吗?

3 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:1)

简答:

你不能。


长答案:

如果您确实需要这样做,则需要在要跟踪的所有方法中执行日志记录代码。

您可以创建一个全局变量(ugh)来存储带有最后一个被调用方法的MethodInfo,并在每个方法中将其设置为MethodBase.GetCurrentMethod()。然后,只要您需要,您可以检查该变量以查看它的最后设置方法。


在您的情况下,您可能正在尝试确定引发异常的方法。您正在查看TargetSite,它返回层次结构中的最低方法,而您似乎想要紧接在现行方法。如果仅仅检查Exception.StackTrace没有提供足够的信息,您可以解析StackTrace中的信息并使用反射获得MethodInfo。通常,StackTrace足够好了。

您也可以在顶级方法中抛出新的异常,这样您就可以从新的异常中获取TargetSite

要点:

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

  • 在要检查的每种方法中执行日志记录代码。
  • 解析您可以从Exception获取哪些信息。
  • 更改异常抛出方案,以便将InnerException设置为原始异常时抛出新异常。

答案 2 :(得分: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”。我仍然不确定你为什么要这样做..因为堆栈跟踪实际上会显示你在失败后从哪里解开。