Get name of last called method

╄→尐↘猪︶ㄣ 提交于 2019-12-11 04:49:19

问题


I have the following code:

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

I need to get in "catch block" name of last called method (in this case "CheckValue"), but it return that called method is "StringToNumber".

I try to get it using StackTrace:

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

It's possible to do this?


回答1:


Short Answer:

Yes, You can!!!


I'd just play around with Extension Methods and the trick here, is to get the last frame of the desired class, otherwise it would get methods of mscorlib assembly. So here it go:

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



回答2:


Short Answer:

You can't.


Long Answer:

If you really need to do that, you will need to perform logging code in all the methods you want to track.

You can create a global variable (ugh) to store a MethodInfo with the last called method, and inside every method, set it to MethodBase.GetCurrentMethod(). Then whenever you want, you can examine that variable to see which method set it last.


In your case, you probably are trying to determine which method the exception was thrown in. You are looking at TargetSite, which returns the lowest method in the hierarchy, whereas you seem to want the one immediately below the current method. If simply examining Exception.StackTrace doesn't provide enough information, you might be able to parse out information from StackTrace and use reflection to get a MethodInfo. Usually, the StackTrace is good enough.

You may also be able to throw a new exception in the top-level method, so you can get the TargetSite from the new one.

Summary:

If Exception.StackTrace doesn't provide enough information, then you will either have to:

  • Perform logging code in each method you want to check for.
  • Parse out what information you can get from the Exception.
  • Change the exception throwing scheme to throw a new exception with InnerException set to the original exception.



回答3:


I don't know why you want to do this.. because this is expected behaviour. The site of the exception is what you're being shown.. within the int.Parse() calls.

That being said.. if you really want to do this, you need to wrap a try.. catch in CheckValue, and re-throw the exception from there, but in a way that breaks the call stack.. like so:

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

Then, ex.TargetSite.Name == "CheckValue". I'm still not sure why you'd want to do this.. as a stack trace will actually show you where it all unwinds from after failure.



来源:https://stackoverflow.com/questions/11794081/get-name-of-last-called-method

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!