获取引发异常的方法名称

Sar*_*avu 17 c# exception

我知道.类似的问题已经提出过了.

但我还没有得到确切的解决方案.

我有一个按钮点击事件,我有一个方法FillCombo().

按钮单击事件

private void button1_Click(object sender, EventArgs e)
{
      try
      {
          cmbTemplates.Items.Clear();
          lstFiles.Clear();
          FillCombo();                
      }
      catch (Exception ex)
      {
           MethodBase site = ex.TargetSite;
           Log(ex.ToString(), site == null ? null : site.Name);                
      }
}
Run Code Online (Sandbox Code Playgroud)

当我调试时,我发现异常发生在FillCombo()方法中.在那之后,我得到的值site.Name作为WinIOError代替FillCombo.

我尝试了另一种方法GetExecutingMethodName(),由Chris Gessler如何获取导致异常问题的方法的名称中回答.所以我尝试使用GetExecutingMethodName()方法发送导致异常的方法名称

Log(ex.ToString(), GetExecutingMethodName());
Run Code Online (Sandbox Code Playgroud)

但我得到的结果System.Windows.Forms.Control.OnClick不是FillCombo.

如何获取导致异常的方法的实际名称?

Me.*_*ame 16

.net支持从异常中获取堆栈跟踪信息.您可以通过检查第一帧(原点)来过滤掉方法(及其名称).

new StackTrace(ex).GetFrame(0).GetMethod().Name
Run Code Online (Sandbox Code Playgroud)

这可能会给你与targetite(win io)完全相同,但你可以检查第一个用户代码的堆栈跟踪,或类型中的第一个框架,或者你需要的任何一个.

例如,获取当前程序集中罪魁祸首的名称:

var s = new StackTrace(ex);
var thisasm = Assembly.GetExecutingAssembly();                
var methodname = s.GetFrames().Select(f => f.GetMethod()).First(m => m.Module.Assembly == thisasm).Name;
Run Code Online (Sandbox Code Playgroud)


Pet*_*iho 9

重要的是要理解"抛出异常的方法"的含义.发生异常时,会有一个实际执行的特定方法.只是因为在异常之前的某个时刻,你调用了自己的FillCombo()方法,这并不意味着抛出异常的方法.

FillCombo()但是,该方法(在您关心的情况下)将在堆栈跟踪中.这就是为什么记录整个堆栈跟踪很有用的原因.实际上,我通常只记录整个Exception对象(即ex.ToString(),或者只是将异常对象传递给string.Format()或者类似的,它会调用ToString()你).这将包括异常类型,消息,整个堆栈跟踪,甚至内部异常信息(如果存在).


你从另一个问题得到的代码,对于这个GetExecutingMethodName()方法,并不是真正有用的恕我直言.你会注意到它真正做的是爬行当前执行位置的堆栈跟踪,寻找在声明的类型之外的类型中声明的第一个方法GetExecutingMethodName().

出于两个原因,这对您的目的是错误的:

  1. 看来你已经在声明了Click事件处理程序的同一个类中声明了该方法.这意味着忽略了事件处理程序方法,因此您获得该方法的调用者,即Control.OnClick()方法(即实际引发事件的方法).

坦率地说,我发现特定的答案很奇怪,因为.NET已经提供了一个API来检索MethodInfo当前正在执行的方法:MethodBase.GetCurrentMethod.这比克里斯盖斯勒写的代码更可靠.

  1. 更有问题的是,您没有机会在抛出异常时调用此方法!充其量(即使你处理了声明帮助方法的位置的问题),所有调用它的人都会告诉你,你在你的button1_Click()方法中.但是你已经知道了,因为你编写的用于处理异常的代码就是在那个方法中.


如果您想知道在异常发生之前调用的当前正在执行的方法中的方法名称,可以将这两种技术结合起来:获取当前正在执行的方法的名称,然后将其传递给同时采用这两种方法的方法和来自Exception对象的堆栈跟踪字符串,并让该方法解析堆栈跟踪字符串,以便在跟踪中当前正在执行的方法之前找到该帧.

这有点痛苦,但可以做到.这是一个例子(简单的概念验证控制台程序):

static void Main(string[] args)
{
    try
    {
        CallForException();
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception occurred calling {0} method", GetCallForExceptionThisMethod(MethodBase.GetCurrentMethod(), e));
    }
}

private static string GetCallForExceptionThisMethod(MethodBase methodBase, Exception e)
{
    StackTrace trace = new StackTrace(e);
    StackFrame previousFrame = null;

    foreach (StackFrame frame in trace.GetFrames())
    {
        if (frame.GetMethod() == methodBase)
        {
            break;
        }

        previousFrame = frame;
    }

    return previousFrame != null ? previousFrame.GetMethod().Name : null;
}

private static void CallForException()
{
    DoActualException();
}

private static void DoActualException()
{
    throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)

最后,请记住,由于方法内联和其他优化,即使是完整的堆栈跟踪也可能存在一些不规则性,包括甚至没有抛出异常的方法的实际名称.这是记录整个Exception对象通常更有用的另一个原因; 环境越多,你就越有可能重建发生的事情.


小智 6

试试这个:

var methodFullName = exception.TargetSite.ReflectedType.FullName 
Run Code Online (Sandbox Code Playgroud)