2014-01-20 40 views
8
private void Method1() 
{ 
    //Do something 
    Log("Something","Method1"); 
} 

private void Method2() 
{ 
    //Do something 
    Log("Something","Method2"); 
} 

private void Log(string message, string method) 
{ 
    //Write to a log file 
    Trace.TraceInformation(message + "happened at " + method); 
} 

我有幾個方法像上面的Method1和Method2,我想通過方法的名稱作爲參數,而不需要手動編輯代碼的方式。傳遞方法的名稱作爲參數

這可能嗎?

+3

有一個稱爲['CallerMemberNameAttribute'](http://msdn.microsoft.com/zh-cn/library/system.runtime.compilerservices.callermembername屬性)的新屬性(我認爲在4.5中,需要最新的編譯器) (v = vs.110).aspx)完成這個,但是在編譯時使用字符串文字。或者,您可以使用linq表達式並查詢表達式本身的名稱,這通常是爲'INotifyPropertyChanged'等屬性完成的。 –

+1

而不是傳遞方法名稱,您可以使用反射 –

+1

請參閱http://stackoverflow.com/questions/2652460/c-sharp-how-to-get-the-name-of-the-current-method-from-代碼 –

回答

4

Jon Skeet的優秀答案。

但是,如果您不使用.NET 4.5,您可以嘗試reflection。你應該怎麼知道reflection must be used only when it is absolutely necessary. Do not over-use it for the sake of using it

走回來的 你可以做這樣的事情,

using System.Reflection; //include Reflection namespace 

Console.WriteLine(MethodBase.GetCurrentMethod().Name) //Get the method-name of the current method 

在你的情況下,它會像下面,

private void Method1() 
{ 
    //Do something 
    Log("Something", System.Reflection.MethodBase.GetCurrentMethod().Name); 
} 

private void Method2() 
{ 
    //Do something 
    Log("Something", System.Reflection.MethodBase.GetCurrentMethod().Name); 
} 

private void Log(string message, string method) 
{ 
    //Write to a log file 
    Trace.TraceInformation(message + "happened at " + method); 
} 

編輯:

按以下來自@Jon Skeet的評論,如果你想.Net 4.5一種花哨和整潔的實施,檢查出 NUGET包。

+0

我不能使用.NET 4.5或5,所以反射似乎只能這樣做。 – gorkem

+0

有什麼意義?您可以簡單地將參數中的方法名稱,因爲您實際上知道它的名稱,當您編寫代碼時。這不是解決問題的辦法,只是幫助複製代碼更簡單。 –

+0

@ArtyomNeustroev:因爲OP不能使用'.NET 4或.NET 4.5',所以我認爲他留下了上述選擇。如果'方法名稱'將來會改變,或者如果有更多的方法呢?雖然這可以幫助複製粘貼代碼更容易,但沒有其他優雅的解決方案(如果您不使用.NET 4或.Net 4.5) –

15

由於C#5,這是一個使用caller info attributes非常簡單:

private void Method1() 
{ 
    //Do something 
    Log("Something"); 
} 

private void Method2() 
{ 
    //Do something 
    Log("Something"); 
} 

private void Log(string message, [CallerMemberName] string method = null) 
{ 
    //Write to a log file 
    Trace.TraceInformation(message + "happened at " + method); 
} 

在得到這個工作方面:

  • 必須可以使用C#5(或更高版本)編譯器,否則它將不知道專門處理屬性。
  • 屬性必須存在於目標環境中。選項有:
    • 在.NET 4.5的屬性只是目前
    • 對於.NET 4,你可以使用Microsoft.Bcl NuGet package
    • 對於早期版本的.NET,複製attribute declaration到你自己的代碼,並確保您使用相同的命名空間。當您稍後轉到.NET的新版本時,您需要再次將其刪除。
+0

優秀的答案喬恩。只是好奇:在'單元測試'的情況下,這個屬性的表現如何?我們可以模擬嗎? –

+1

@nowhewhomustnotbenamed .:這是一個編譯時的事情 - 編譯器注意到該參數已用該屬性修飾並且具有默認值null,並且調用方未提供參數,因此它使用成員名稱代替。我不確定你說的是什麼樣的嘲弄,但你可以很容易地明確地傳遞一個參數(例如'Log(「message」,「NotARealMethod」)) –

+0

感謝Jon。 '可選參數'。說得通。 :) –

0

面向方面編程(AOP)通常可以實現這樣的任務。你可以看看PostSharp的免費版本,特別是Logging aspect對你有幫助。然後

你的代碼如下所示:

[LogAspect("Something")] 
void Method1(string name) 
{ 

} 

您可以使用PostSharp到.NET框架2.0。