2012-05-07 71 views
3

我正在用C#編寫一個函數來記錄用戶在我們系統上的操作並將它們保存在數據庫中。具體而言,我想記錄業務邏輯的某些功能,因爲它們被稱爲。我來到約測井方法是這樣的:記錄器方法設計

public static LogMethod(string user, string methodName, object[] parameters, string message) 

內適當ToString()函數被調用爲每個參數的方法。 例如,對於foo方法它被稱爲是這樣的:

void Foo(int a, SomeObject b) 
{ 
    Logger.LogMethod(username, "Foo", new object[]{a,b}, "Beginning Foo"); 
    //etc 
} 

是它記錄的函數調用的好方法?實現這一目的的最佳實踐是什麼? 會影響性能嗎?

+0

你可以只使用微軟[登錄應用程序塊(http://msdn.microsoft.com/en參數的名稱-us /庫/ ff664569%28V = pandp.50%29.aspx)? –

+1

僅供參考 - log4net的已經DB集成內置的,可能是有用的:http://logging.apache.org/log4net/release/config-examples.html –

回答

3

是的,它會影響性能,因爲您必須使用反射來獲取MethodInfo並調用它。除此之外,它會殺死可維護性,因爲你不能重構方法名稱。

看一看以下之前常見&一種替代方案:How do I intercept a method call in C#?

3

不要亂丟垃圾與錄入邏輯,這是一個橫切關注點你美麗的業務邏輯。你應該使用一種像攔截方法的技術來攔截你想記錄的方法。

這是記錄函數調用的好方法嗎?

不,不是,坦率地說。您的代碼現在正在執行您的業務邏輯和日誌記錄。這是難以編寫,難以測試並且很難維護的代碼。

實現此目的的最佳實踐是什麼?

我鼓勵你找到一個方法來解決這個問題,不涉及任何地方破壞與日誌記錄代碼代碼。標準的解決方案是使用方法攔截或面向方面的編程。有很多方法可以實現這一點(你可以使用許多框架之一來設置它,但我偏愛Castle Windsor)。

會影響性能嗎?

只有你可以回答這個問題。如果你記錄的東西像用戶正在做的事情,不太可能。用戶很蠢,而且他們使用的磁盤和數據庫速度很慢,所以不太可能在乎你是否需要花費幾毫秒來記錄某些內容。我們不是在討論關鍵循環。 但是,只有您可以決定它是否慢得令人無法接受,並且只有您可以測量自己的應用程序,無論是否使用日誌記錄來查看它是否無法接受地很慢。

+0

謝謝你,起初我考慮如春,團結,或工具城堡溫莎但學習它們,並將它們組合成我的項目可能是太耗費我的當前項目的時候,您的評論吸引了我尋找更多關於AOP的解決方案,我終於停在PostSharp,它看起來像一個良好的適合我的需要。謝謝。 – hhsaffar

2

正如其他人已經指出的,一個AOP框架可能是一條路。


如果你還是想用你的方法,你可以做一個小的改進它。如果您將參數放在最後,您可以使用params關鍵字。

public static LogMethod(string user, string methodName, string message, 
         params object[] parameters) 

這使得調用該方法稍微容易一些。

void Foo(int a, SomeObject b) 
{ 
    Logger.LogMethod(username, "Foo", "Beginning Foo", a, b); 
    //etc 
} 
+0

的參數重排是一個好主意! – hhsaffar

2

一切都會影響性能,但效果是否「不好」是主觀的。這也完全取決於你多久打電話給方法。

如果rearrage的參數和使用params關鍵字,可以簡化電話:

public static LogMethod(string user, string methodName, string message, params object[] parameters) 

現在您的通話更簡單:

Logger.LogMethod(username, "Foo", "Beginning Foo", a, b); 

沒有必要申報對象數組,編譯器會爲你處理這個問題。見params

此外,您還可以通過從堆棧獲取調用方法名簡化電話:

public static LogMethod(string user, string message, params object[] parameters) 
{ 
    string methodName = new StackFrame(1).GetMethod().Name; 
    ...  
} 

現在你不需要methodName參數的。 (在.NET 4.5,可以實現與CallerMemberNameAttribute同樣的事情。)

與反思,你可以走的更遠;比如,你可以得到傳遞給調用方法的類的名稱等

+0

感謝您的信息。 – hhsaffar