从方法中检索调用方法名称[重复]
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中调用方法详细信息,例如行号,方法名称和类名称[重复]