2012-06-30 69 views
5

我注意到,.NET 4.5有一个新的属性,称为[CallerMemberNameAttribute]它附加到方法的参数时,将提供名为方法(如果这是有道理的)。c#获取调用方法没有堆栈跟踪

然而,不幸的是(因为我想与XNA做一些事情),我只针对.NET 4.0。

我希望能够做一些事情,如:

void MethodA() { 
    MethodB(); 
} 

void MethodB() { 
    string callingMethodName = (...?); 
    Console.WriteLine(callingMethodName); 
} 

凡我输出将治法

我知道我可以通过堆栈跟踪做到这一点,但这是一个)不可靠和b)Sloooow ... 所以我不知道是否有任何其他方式来收集这些信息,但是这可能是...

我一直希望任何人有任何想法或知识可以解决这个问题。在此先感谢:)

+3

作为字符串传入调用方法名称? – Oded

+2

@Oded很明显,我可以调用MethodB(“MethodA”),但重点是我试图动态执行它,所以如果我将MethodA更改为MethodC,则不必编辑该调用。 – Xenoprimate

+0

你在这个问题上没有提到这一点。 – Oded

回答

13

如果您使用Visual Studio 2012编译此代码,则可以编写自己的CallerMemberNameAttribute,并以与.NET 4.5相同的方式使用它,即使您仍以.NET 4.0或3.5为目标。编译器仍然会在编译时执行替换,甚至针对较旧的框架版本。

只需添加以下到您的项目将这样的伎俩:

namespace System.Runtime.CompilerServices 
{ 
    public sealed class CallerMemberNameAttribute : Attribute { } 
} 
+0

我只是一个业余爱好者程序员,所以很抱歉,如果这是一个愚蠢的问题,但有没有办法我可以看到微软的CallerMemberNameAttribute的来源?我的意思是复制它。 – Xenoprimate

+2

一般来说,是的,您可以使用ILSpy来反编译.NET库。 http://wiki.sharpdevelop.net/ILSpy.ashx然而,属性很少会产生任何有趣的结果,因为有趣的是它更多地被其他代码使用。例如。从@ReedCopsey的说法来看,转换是在编译时由编译器完成的,而不是由属性本身完成的,而且你甚至不需要.NET 4.5运行库,所以你很可能看不到有趣的代码。 –

+0

啊,所以编译器只看到名字'CallerMemberNameAttribute'并插入它自己的逻辑?如果是这样,我可以创建一个具有该名称的空白属性,它会起作用吗? – Xenoprimate

0

你可以作为参数调用方法提供来电者姓名。不太你要求什么,但它的工作原理,而无需访问堆栈帧:

[MethodImpl(MethodImplOptions.NoInlining)] 
void MethodA() 
{ 
    string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; 
    MethodB(methodName); 
} 

void MethodB(string callingMethodName) 
{ 
    Console.WriteLine(callingMethodName); 
} 

使用MethodBase.GetCurrentMethod(),可以确保您的落实仍然是重构安全 - 如果你的方法的名称更改,结果仍然是正确的。

不要忘记用MethodImplOptions.NoInlining标记您的调用方法,以避免方法内联。