从方法中检索调用方法名称[重复]

Posted

技术标签:

【中文标题】从方法中检索调用方法名称[重复]【英文标题】:Retrieving the calling method name from within a method [duplicate] 【发布时间】:2010-10-11 14:01:42 【问题描述】:

我在一个对象中有一个方法,该方法从对象中的多个位置调用。有没有一种快速简便的方法来获取调用这个流行方法的方法的名称。

伪代码示例:

public Main()

     PopularMethod();


public ButtonClick(object sender, EventArgs e)

     PopularMethod();


public Button2Click(object sender, EventArgs e)

     PopularMethod();


public void PopularMethod()

     //Get calling method name

PopularMethod() 内,如果Main 是从Main 调用的,我想查看它的值...如果PopularMethod()ButtonClick 调用,我想查看“ButtonClick

我正在查看System.Reflection.MethodBase.GetCurrentMethod(),但这不会让我获得调用方法。我查看了 StackTrace 类,但我真的不喜欢每次调用该方法时都运行整个堆栈跟踪。

【问题讨论】:

【参考方案1】:

我认为您确实需要使用 StackTrace 类,然后在下一帧使用 StackFrame.GetMethod()

不过,使用Reflection 似乎是一件奇怪的事情。如果您正在定义PopularMethod,则无法定义参数或其他东西来传递您真正想要的信息。 (或者放在基类或其他东西上......)

【讨论】:

【参考方案2】:

我经常发现自己想要这样做,但总是最终重构我的系统设计,所以我没有得到这种“摇尾巴”的反模式。结果始终是更强大的架构。

【讨论】:

【参考方案3】:

在 .NET 4.5 / C# 5 中,这很简单:

public void PopularMethod([CallerMemberName] string caller = null)

     // look at caller

编译器会自动添加调用者的名字;所以:

void Foo() 
    PopularMethod();

将传入"Foo"

【讨论】:

此解决方案的性能后果是什么? @Feckmore none :编译器在编译期间将其添加为文字。它比查看 StackTrace 等任何东西都要快得多。基本上它被编译为 PopularMethod("CurrentMethodName") 我收到一条错误消息,提示找不到 CallerMemberName。 VS Express C# 2010 @user396483 您需要以 .NET 4.5 或更高版本为目标才能使属性存在(尽管您可以自己定义),并且您需要使用 C# 5 才能以所需的方式工作. VS Express 2013 可用且免费【参考方案4】:

只需传入一个参数

public void PopularMethod(object sender)



IMO:如果它对事件来说足够好,那么它应该足够好。

【讨论】:

Sruly - 是的,这绝对是一个选择,我试图在不改变方法调用的情况下做到这一点。这将是我最后的选择。 除非您将其公开为公共 API,否则如果您可以这样做,为什么还要麻烦并使用反射呢?记住亲吻 这是最好的答案,不要使用反射或其他东西,通过参数识别调用者。 如果您正在寻找命名空间/程序集信息之类的信息,则传递类型可能是更好的选择,因为调用可能来自静态方法。 我为许多系统编写过代码。开发人员通常希望跟踪正在编写日志条目的方法。如果日志代码需要手动传递方法名,这就需要开发者在每次调用日志方法时都将方法名作为文本输入。现在在程序的许多不同部分使用相同的日志记录方法,看看几年内与许多开发人员一起添加、删除和重命名方法会发生什么。自动传递调用者的方法名将极大地简化开发和调试。【参考方案5】:

这其实很简单。

public void PopularMethod()

    var currentMethod = System.Reflection.MethodInfo
        .GetCurrentMethod(); // as MethodBase

但是要小心,我有点怀疑内联方法是否有任何效果。您可以这样做以确保 JIT 编译器不会妨碍您。

[System.Runtime.CompilerServices.MethodImpl(
 System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()

    var currentMethod = System.Reflection.MethodInfo
        .GetCurrentMethod();

获取调用方法:

[System.Runtime.CompilerServices.MethodImpl(
 System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()

    // 1 == skip frames, false = no file info
    var callingMethod = new System.Diagnostics.StackTrace(1, false)
         .GetFrame(0).GetMethod();

【讨论】:

John Leidgren - 这会让我得到“PopularMethod”这个名字,但我想要名为 PopularMethod 的方法的名称。 对,那么堆栈跟踪就是您所需要的。我看错了你的问题。 只用 .GetFrame(1) 代替吧? +1 表示MethodInlining.NoInlining。顺便说一句,StackTrace .ctor 调用上的 false 是多余的,不是吗? 如果我没有明确要求文件信息,我相信它确实表现出稍微更好的性能。说实话,这可能没关系,我这样做的主要原因是因为我不需要文件信息。【参考方案6】:

虽然您可以最明确地跟踪堆栈并以这种方式计算出来,但我会敦促您重新考虑您的设计。如果您的方法需要了解某种“状态”,我会说只需创建一个枚举或其他东西,并将其作为您的 PopularMethod() 的参数。类似的东西。根据您发布的内容,跟踪堆栈将是 IMO 过度杀伤力。

【讨论】:

【参考方案7】:

我认为不跟踪堆栈就无法完成。但是,这样做相当简单:

StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
Console.WriteLine(methodBase.Name); // e.g.

但是,我认为你真的必须停下来问问自己这是否有必要。

【讨论】:

欲了解更多信息,请参阅:discuss.joelonsoftware.com/default.asp?dotnet.12.511358.10 System.Diagnostics 是 StackTrace 的命名空间,System.Reflection 是 MethodBase 的命名空间。 Jason - 谢谢,我不确定“StackTrace”方法的资源密集程度如何,但这确实让我得到了我想要的东西。这对我来说只是一个调试代码块,不会投入生产。再次感谢您的帮助! @Scott Vercuski - 这是一项非常昂贵的操作,如果有任何方法可以避免这种情况,你真的应该这样做。它比抛出异常更糟糕,这很糟糕。能做固然好,但不能乱用。 @John Leidegren - 绝对......这不会进入生产代码,我们只是在做一些大规模的 QA 测试并发生一些奇怪的事情,这只是为了帮助找出问题所在走火入魔。谢谢!

以上是关于从方法中检索调用方法名称[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在android中调用方法详细信息,例如行号,方法名称和类名称[重复]

从通过反射调用的 COM 方法中检索原始错误号

尝试在sqlite中的空对象引用上调用虚拟方法[重复]

如何通过字符串方法名称在类内调用python静态方法[重复]

通过重复对象名称来调用静态方法?

显示来自sqlite数据库的数据时“尝试在空对象引用上调用虚拟方法”[重复]