2012-06-30 67 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標記您的調用方法,以避免方法內聯。