2012-10-25 22 views
1

C#不支持C/C++宏。在StackOverflow中有很多Q & A與此相關,但我無法找到特定問題的答案。如何裝飾C#中的代碼無需C/C++ - 像宏一樣

讓說我使用的代碼就像一個建議,在http://logging.apache.org/log4net/release/faq.html

if(log.IsDebugEnabled) 
{ 
    log.Debug("Entry number: " + i + " is " + entry[i]); 
} 

這種方式來啓用/禁用記錄有明顯的缺點。在C++中,我會使用像LOG(expr)這樣的宏來提高代碼的可讀性並更好地控制'if(log.IsDebugEnabled)'部分代碼(可能在項目中重複數千次)。

我該如何實現LOG(expr) - 就像C#中的結果一樣?

謝謝!

+1

您可以嘗試面向方面的編程參見[PostSharp(HTTP的簡單串聯://www.sharpcrafters .COM /解決方案/日誌#)。 – Rafal

+0

將IsDebugEnabled測試移動到記錄器調試功能。 –

+2

僅僅因爲從閱讀你的問題可能不明顯,你要找的是一種在運行時**開關記錄器的方法**,並確保'log.Debug'的參數是沒有評估*根本*如果日誌記錄被禁用,是正確的? – jalf

回答

1

使用新的log4net XXXXFormat方法,而不是。他們以這種方式實現:

public virtual void DebugFormat(string format, params object[] args) 
{ 
    if (this.IsDebugEnabled) 
    { 
     this.Logger.Log(declaringType, m_levelDebug, String.Format(format, args)); 
    } 
} 

你也將有String.Format力量,而不是字符串

log.DebugFormat("Entry number: {0} is {1}", i, entry[i]); 
+0

謝謝,這也可以是一個解決方案,雖然我不喜歡格式。在我使用log4cxx的C++代碼中,我使用流操作(<<)。所以在C#中,我的首選項可能是+(在故事的結尾,我需要構建一個單一的字符串寫入記錄器) – mvidelgauz

+1

@mvidelgauz在C#中使用'+'在內存中產生許多字符串。即'a + b + c + d'會產生'ab','abc'和'abcd'字符串。使用'String.Format'處理字符串是有效的,並且不會創建額外的字符串 –

0

作爲一個想法,您可以使用一個靜態方法創建類,該方法將接受字符串表達式。

0

...部分代碼(這可能是在 項目重複000次)。

每當你想到這樣的事情時,首先應該在你腦海中彈出的是encapsulate, encapsulate, encapsulate

你可以簡單地創建你自己的記錄器類,它有一個IsDebugEnabled屬性和你自己的Log方法。

void Log(string message) 
{ 
    if (IsDebugEnabled) 
    { 
    log.Debug(message); 
    } 
} 

可能更好地到處尋找現有記錄庫,這可能已經支持你所需要的所有功能。

E.g. log4net

+3

正如我所理解的問題,這隻能解決一半的問題:他希望能夠在運行時切換日誌記錄(您的示例允許),但是*也*能夠避免在記錄被禁用時評估'message' 。 (例如,我打電話給你的函數是這樣的:'Log(expensiveFunction())',如果日誌記錄被禁用,我不想'expensiveFunction'被調用:) – jalf

+1

好點,我只是因爲你的地址已經寫好了,所以請在這裏回答這個問題。 :)我相信OP有足夠的信息可用。 –

1

可以將其定義爲一種方法和其標記爲調試器條件:

internal static SomeClass 
{ 
    [Conditional("DEBUG")] 
    internal static void Log(string expr) 
    { 
    //... 
    } 
} 

如果沒有定義,編譯器常數「調試」,編譯器將刪除此方法和任何呼叫或參照該方法。是的,它也適用於其他人。它類似於:

internal static SomeClass 
{ 
    #if DEBUG 
    internal static void Log(string expr) 
    { 
    //... 
    } 
    #endif 
} 

但是使用它不會刪除對此方法的引用,因此您也必須將它們封裝起來。


是的,這隻允許在編譯時禁用日誌。 jalf有一個better approach在運行時處理此問題。

+0

,做一些完全不同的事情... – jalf

+0

由於OP的問題還不太清楚,所以還是相關的信息。 –

+0

謝謝Theraot!我不知道[Conditional(「DEBUG」)],我會試試它。它會消除構造字符串參數的不必要的代碼嗎? Jalf,我知道這是一種不同的方法,但如果我想在編譯時禁用日誌記錄,這也是有用的,對嗎? – mvidelgauz

3

你不能......因爲C#沒有宏!

當然,你可以做這樣的事情,而不是:

定義日誌函數,它接受一個lambda

void Log(Func<string> f) { 
    if(log.IsDebugEnabled) 
    { 
    log.Debug(f()); 
    } 
} 

,當你想記錄的東西這樣稱呼它:

Log(()=>"Entry number: " + i + " is " + entry[i]); 

這樣,只有在啓用日誌記錄時纔會評估參數,我認爲這是您想實現的目標。

(我的C#是有點生疏,所以語法可能稍微偏離)

+0

爲什麼使用lambda? :) –

+3

禁止記錄被禁止時評估參數。假設你想記錄一個非常昂貴的函數調用的結果。如果禁用日誌記錄,則不應該調用這個非常昂貴的函數。 – jalf

+0

啊...我注意到他現在正在談論的那部分文檔。 _「如果你擔心速度」_ ......我不知道他擔心速度。 –

-1

面向方面編程是你想要什麼,因爲事情像記錄和緩存有什麼與你的業務邏輯。所以他們應該分開。

有許多框架可用,請看postsharp(http://www.sharpcrafters.com/)或snap(http://www.simpleaspects.com/)。如果您使用支持的依賴注入框架之一,也許snap是不錯的選擇。

UPDATE:如果你正在使用log4net的,你應該能夠從配置文件將其關閉,<log4net threshold="OFF" />所以,你應該有一個調試配置和釋放配置

+0

AOP是相關的,但不確定它是否會在他的特定情況下幫助OP,那麼我們需要更多信息。 –

+0

是的,你說得對,但是在任何地方使用LOG()都只是醜陋而分散注意力。我會重構和使用aop。 – user1736525

相關問題