2012-06-20 18 views
2

想不起更好的標題禁用的參數評估,隨意改變它的東西更好:)如何在方法

我的應用程序中含有大量的日誌報表,這樣的事情:

var logger = new Logger(/*..get flag from settings if the logger should be active..*/); 
// .... 
logger.LogActivity(..serialize an object..); 
//... 
logger.LogActivity(..get another object's expensive overriden ToString method..); 
//... 
logger.LogActivity(..log something new..); 

Logger類:

public class Logger 
{ 
    private readonly bool _isActive; 

    public Logger(bool isActive) 
    { 
    _isActive = isActive; 
    } 

    public void LogActivity(string activity) 
    { 
    if (_isActive) 
    { 
     // Save activity to Database. 
    } 
    } 
} 

當我禁用設置記錄器(所以在Logger類的_isActive場是假的),那麼什麼都被保存到數據庫中。但是Logger.LogActivity方法中的所有表達式仍然被評估(例如前面例子中的..serialize對象),這會降低我的應用程序的速度。 我可以使用日誌語句是這樣的:

var logger = new Logger(/*..get flag from settings if the logger should be active..*/); 
// .... 
if (loggerIsActive) logger.LogActivity(..serialize an object..); 
//... 
if (loggerIsActive) logger.LogActivity(..get another object's expensive overriden ToString method..); 
//... 
if (loggerIsActive) logger.LogActivity(..log something new..); 

但它會更好只改變LogActivity方法...是否有可能以某種方式改變只LogActivity方法,以便在情況下,當記錄器被禁用, LogActivity調用中的表達式不被評估?好吧 - 如果在C#中可以這樣做,我會感到驚訝,但是有沒有其他方式/模式可以做到這一點?

+3

傳遞一個lambda表達式? – kenny

+1

爲什麼你沒有像IsLoggerActive這樣的方法來檢查記錄器是否激活,然後開始記錄? –

回答

3

您可以添加一個重載,該重載需要一個Func<string>來生成要記錄的字符串。

public void LogActivity(Func<string> activity) 
{ 
    if (_isActive) 
    { 
     string log = activity(); 
     // save 'log' to database 
    } 
} 

然後使用它是這樣的:

logger.LogActivity(() => expensiveObject.ToString()); 
+0

但是然後LogActivity總是被調用... – RvdK

+0

這將導致最醜陋的代碼 - 我不羨慕任何人閱讀所有這些lambda表達式的日誌代碼。 – zmbq

+1

是的,但問題是關於如何不評估函數的參數,因爲這並不總是需要執行的昂貴的操作。這會在編譯時創建一個lambda表達式,您可以在運行時決定是否評估。 – Martin

1

不能避免參數評測完全沒有,但你可以提供一些額外的測井方法,可以幫助你在這裏。

@Martin和@kenny建議傳遞lambda表達式。這將推遲對代碼的評估,但會導致醜陋的客戶端代碼。您可能會節省幾個週期,但我懷疑這是否值得。

我建議你創建幾個LogActivity覆蓋:

LogActivity(string message) // logs the message 
LogActivity(object obj) // calls obj.ToString() and logs it 

並保持lambda表達式變種,如果你覺得真的有必要:

LogActivity(Func<String> func) // evaluates the function and logs its response 

注意,你將無法避免調用LogActivity的成本。 C#不是C,而且你沒有像C那樣工作的宏。這不是問題,如果調用一個非虛方法對你來說代價昂貴,你經常這樣做,你不應該這樣做無論如何,在那裏放置日誌消息。