【问题标题】:How to get the name of the method that caused the exception如何获取导致异常的方法的名称
【发布时间】:2011-01-04 20:48:40
【问题描述】:

我的代码如下所示。

try
{
    _productRepo.GetAllProductCategories();
}
catch (Exception ex)
{
    //Do Something
}

我需要一种显示方法名称的方法,假设在上述情况下,如果在 GetAllProductCategories() 方法中引发任何异常,我需要获取此方法名称,即“GetAllProductCategories()”作为我的结果。谁能建议我如何做到这一点?

【问题讨论】:

标签: c# exception-handling try-catch


【解决方案1】:

System.Exception 上有一个 TargetSite 属性应该会派上用场。

获取抛出的方法 当前异常。

在你的情况下,你可能想要这样的东西:

catch (Exception ex)
{
   MethodBase site = ex.TargetSite;
   string methodName = site == null ? null : site.Name;
   ...           
}

值得指出的一些问题:

如果抛出这个的方法 例外不可用,并且 堆栈跟踪不是空引用 (Visual Basic 中没有),TargetSite 从栈中获取方法 痕迹。如果堆栈跟踪为空 参考,TargetSite 也返回一个 空引用。

注意:TargetSite 属性可能不 准确申报姓名 发生异常的方法 如果异常处理程序抛出 处理异常 应用程序域边界。

您也可以按照@leppie 的建议使用StackTrace 属性,但请注意这是堆栈上帧的字符串表示形式;因此,如果您只想要抛出 execption 的方法的 name,则必须进行操作。

【讨论】:

    【解决方案2】:

    它在 StackFrame 中...

    private string GetExecutingMethodName()
    {
        string result = "Unknown";
        StackTrace trace = new StackTrace(false);
        Type type = this.GetType();
    
        for (int index = 0; index < trace.FrameCount; ++index)
        {
            StackFrame frame = trace.GetFrame(index);
            MethodBase method = frame.GetMethod();
    
            if (method.DeclaringType != type && !type.IsAssignableFrom(method.DeclaringType))
            {
                result = string.Concat(method.DeclaringType.FullName, ".", method.Name);
                break;
            }
        }
    
        return result;
    }
    

    此方法是为 Logging 处理程序类编写的,使用 GetType() 可以简单地消除 Logging 处理程序类中的方法作为最后一个执行方法返回。由于 Logging 处理程序类不仅仅是为记录异常而编写的,因此需要一个新的 StackTrace 对象。显然,对于查找“引发异常的方法”,GetType() 可能不是必需的。

    如果您只想要堆栈的顶部,请获取第一帧,调用 GetMethod() 并返回它,或者简单地使用 TargetSite。然后可以删除 GetType()。另请注意,需要传入 Exception 才能创建 StackTrace 对象。例如:

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Test();
            }
            catch (Exception ex)
            {
    
                // does not work properly - writes "Main"
                Console.WriteLine(MethodBase.GetCurrentMethod());
    
                // properly writes "TestConsole.Program.Test"
                Console.WriteLine(GetExecutingMethodName(ex));
    
                // properly writes "Test"
                Console.WriteLine(ex.TargetSite.Name);
            }
    
            Console.ReadKey();
        }
    
    
        static void Test()
        {
            throw new Exception("test");
        }
    
        private static string GetExecutingMethodName(Exception exception)
        {
            var trace = new StackTrace(exception);
            var frame = trace.GetFrame(0);
            var method = frame.GetMethod();
    
            return string.Concat(method.DeclaringType.FullName, ".", method.Name);
        }
    }
    

    基本上,如果 TargetSite() 可以满足您的需求,那么就不要再进一步了。但是,通常在 Logging 处理程序中,异常对象不可用(即跟踪和审计),因此需要一个新的 StackTrace() 对象来检索最后执行的方法,即在 Logging 方法之前的方法。

    【讨论】:

    • GetType 指的是什么?这是您创建的另一种方法吗?内置的 GetType 需要一个对象来引用。
    • @KingOfHypocrites - 正在从当前类调用 GetType()。
    • 我不明白这如何适用于所提出的问题。此代码生成一个全新的StackTrace 对象,与异常的堆栈跟踪无关。此外,.NET 已经有一个非常好的(并且更可靠)的方法来获取当前正在执行的方法的 MethodInfo 对象:MethodBase.GetCurrentMethod
    • @PeterDuniho - 它表明当前执行的方法名称可从 StackFrame 获得。因此,在错误情况下,Exception 对象可用于创建 StackTrace 对象,该对象可用于获取 StackFrames。该方法可以很容易地修改为接受 Exception 对象,但代码更多的是演示如何使用 StackFrame。另请注意 MethodBase.GetCurrentMethod() 将仅提供当前正在执行的方法的名称,而不是引发异常的方法。
    • @ChrisGessler 如何在异步方法中获取方法?堆栈跟踪更复杂,我在这里看不到“真正的”方法名称。
    【解决方案3】:

    查看堆栈跟踪。

    这是异常的一个属性。

    【讨论】:

      猜你喜欢
      • 2014-01-17
      • 1970-01-01
      • 1970-01-01
      • 2016-08-16
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      相关资源
      最近更新 更多