【问题标题】:Getting The Method That A Method Was Called From? [duplicate]获取调用方法的方法? [复制]
【发布时间】:2011-08-05 18:14:36
【问题描述】:

是否可以在 PostError 中确定调用方法名称“Eat Pizza”? 我想我可以将“EatPizza”作为参数之一传递,但是每次方法名称更改时都需要更改(不必要的维护)。但是,我什至无法在“EatPizza”的上下文中找到方法名称“EatPizza”(使用 stacktrace、getframe、getmethod)。

public void EatPizza(Pizza p){
    if(p==null){ //A arbitrary made up error
        Utilities.PostError();
    }
    else{
        p.Slices -= 1;
    }
}

...

public void PostError(){
    //Basically posting to database the name of the method
    //Tried this, didn't work: (new StackTrace(true)).GetFrame(5).GetMethod().Name
    //Is it possible to determine the calling method name "Eat Pizza" in this context?
}

当我在 StackTrace.GetFrame 中尝试不同的值(0 到 StackTrace.FrameCount-1)时,我得到以下值,而我只想要“EatPizza”:

.ctor
ThreadStart
Main
_nExecuteAssembly
RunUsersAssemblyDebugInZone

【问题讨论】:

  • 你知道,抛出异常会得到堆栈跟踪,这是处理错误的推荐方法。你有什么理由不这样做?如果需要,您可以在 catch 块中调用 PostError
  • 我唯一注意到的是您将 5 传递给 GetFrame。我认为您希望当前帧为 0,前一帧为 1。但我也假设您使用它作为您尝试的事物类型的更多演示,而不是您尝试的文字代码。
  • @driis,好的,看起来不错。我现在有一个接受 Exception 参数并发布 Exception.StackTrace 的方法。我喜欢这个解决方案:)

标签: c# methods stack-trace stack-frame getmethod


【解决方案1】:

是否可以在 PostError 中确定调用方法名称“Eat Pizza”?我想我可以将“EatPizza”作为参数之一传递,但是每次方法名称更改时都需要更改(不必要的维护)。

在所有可能出错的方法中调用 PostError 也是“不必要的维护”。它还使程序的执行流程复杂化,因为您必须到处检查错误,而高级进程必须检查低级进程是否成功完成。

最好使用 CLR 和 C# 提供的异常处理结构。

发生错误的确切位置存储在异常的 StackTrace 属性中。

pubic void BigDinnerEatingProcess()
{
    try
    {
         WhateverHappensAtTheTopLevel();
    }
    catch (PizzaNotDeliveredException ex)
    {
         Utilities.PostError(ex);
         MessageBox.Show("Dinner was not eaten. Please make sure the pizza is delivered.");
    }
}

public void EatPizza(Pizza p)
{
    if (p == null)
        throw new PizzaNotDeliveredException();
    p.RemoveOneSlice();
}

private void PostError(Exception ex)
{
    string errorLocation = ex.StackTrace;
    //...
}

【讨论】:

  • +1 表示不必要的复杂性。 @sooprise 如果您决定重构您的日志记录方法,并且 StackTrace.GetFrame 最终深度为 2 级而不是现在的 1 级,该怎么办?然后,您必须手动调整代码中的 +1 帧。
【解决方案2】:

您在创建StackTrace 对象方面走在了正确的轨道上,但您似乎误解了GetFrame 的论点。帧从最底部帧开始编号,因此:

  • GetFrame(0) 将返回 PostError
  • GetFrame(1) 将返回 PostError 的调用者

所以试试这个:

var trace = new StackTrace(true);
WriteToDB(trace.GetFrame(1).GetMethod().Name);

就个人而言,我更愿意获取整个堆栈跟踪,而不仅仅是调用者,所以我会这样做:

var trace = new StackTrace(true);
WriteToDB(trace.ToString());

【讨论】:

  • +1 如果您要使用部分跟踪记录错误,为什么不包括整个事情并获得“大局”的优势?
  • +1,是的,这一切都说得通。堆栈跟踪包含足够的信息用于我的错误记录,谢谢!
猜你喜欢
  • 2012-01-28
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
  • 2013-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多