星期一
情景
早晨,項目組長來到身邊,“有人反映咱們的項目有Bug” “什麼Bug?” “不知道,你添加一個日誌模塊自己看記錄去。” ”...“
分析
在MVC全局過濾器中自己添加有異常過濾器。
Global.asax
View Code
FilterConfig.cs
View Code
開工
整理思路:發生錯誤時要執行自己需要的代碼,只需要繼承IExceptionFilter,重寫OnException方法,然後把自己的過濾器註冊到全局即可。
創建過濾器,MyExceptionFilter類
1 //因爲微軟已經提供了一個HandleErrorAttribute類(它其實也是繼承了IExceptionFilter),所以我們只需繼承它即可
2 public class MyExceptionFilter: HandleErrorAttribute
3 {
4 //重寫OnException方法
5 public override void OnException(ExceptionContext filterContext)
6 {
7 base.OnException(filterContext);
8
9 //把錯誤寫到日誌文件裏面去
10 //思考:如果同時來了多個錯誤,一起向文件中寫內容,就會發生同時訪問同一個文件問題。你會怎麼解決?
11 //提示:鎖、隊列
12
13 //LogHelper類用來把錯誤寫到日誌裏面去
14 LogHelper.Write(filterContext.Exception.ToString());
15
16 }
17 }
LogHelper類,用來把錯誤寫到日誌裏面去
View Code
把自己的過濾器註冊到全局
View Code
自定義錯誤測試
View Code
OK,大功告成,以後就可以根據日誌來找錯誤了。
星期二
情景
早晨,項目組長又來到小身邊,”昨天我用了你的錯誤日誌功能,還不錯,但是你將日誌寫在文件中整理不是太方便,還存在共享衝突問題,你改下寫到數據庫中“ ”...“
分析
查看昨天寫的代碼
發現此處是一個變化點,有可能寫到文件中,有可能寫到數據庫中,有可能......
不就是寫到不同的地方麼,簡單,多態就能搞定了。
開工
依賴於抽象,而不依賴於具體
創建IWriteLog接口
View Code
創建WriteLogToText類實現接口,用來寫入文本
View Code
創建WriteLogToSqlServer類實現接口,用來寫入數據庫
View Code
對變化點進行修改
1 ThreadPool.QueueUserWorkItem(o=> {
2 lock (ExceptionStringQueue) {
3 string exceptionString = ExceptionStringQueue.Dequeue();
4 //依賴接口
5 IWriteLog writeLog = new WriteLogToSqlServer();
6 //IWriteLog writeLog = new WriteLogToText();
7 //把錯誤信息寫到相應的地方
8 writeLog.WriteLog(exceptionString);
9
10 }
11 });
OK,大功告成,又可以去美滋滋了...
星期三
情景
早晨,項目組長再一次來到小身邊,”經過我的思考,我覺得把錯誤信息同時寫到文本和數據庫中比較好“ ”爲什麼?“ “需求” “...”
分析
錯誤信息有可能要寫到不同的地方,而且不知道有多少地方,說不定明天又加了一個Redis、後天再加一個....
這時候我們可以考慮創建一個集合來保存都需要寫到那些地方去。(這裏插一句:設計模式只是一種思想,實現方式肯定是不唯一的,但是思想是精髓,不能說這個代碼是這個模式,換一種方式實現就不是這個模式了。)
然後依次寫入即可。
開工
對LogHelper進行修改鄭州不孕不育醫院:http://jbk.39.net/yiyuanzaixian/zztjyy/鄭州不孕不育醫院哪家好:http://jbk.39.net/yiyuanzaixian/zztjyy/鄭州不孕不育醫院排行:http://jbk.39.net/yiyuanzaixian/zztjyy/
1 public class LogHelper
2 {
3 //添加一個靜態的異常信息隊列,只要出現異常就寫到隊列中。
4 public static QueueExceptionStringQueue = new Queue();
5
6 //定義一個集合來存放所有的 觀察者,
7 public static IListwriteLogList = new List();
8
9 //第一次用到該類型時會執行靜態構造函數,只被執行一次
10 static LogHelper() {
11
12 //觀察(訂閱)
13 writeLogList.Add(new WriteLogToSqlServer());
14 writeLogList.Add(new WriteLogToText());
15
16 //創建一個線程池,將方法排入隊列以便執行
17 ThreadPool.QueueUserWorkItem(o=> {
18 lock (ExceptionStringQueue) {
19 string exceptionString = ExceptionStringQueue.Dequeue();
20
21 //發佈
22 foreach (var writeLog in writeLogList)
23 {
24 writeLog.WriteLog(exceptionString);
25 }
26
27 }
28 });
29 }
30
31
32 //給外部提供方法,將錯誤信息寫入隊列
33 public static void Write(string exceptionString) {
34 lock (ExceptionStringQueue)
35 {
36 //將錯誤信息添加到隊列
37 ExceptionStringQueue.Enqueue(exceptionString);
38 }
39 }
40 }
後期如果還需要寫入其它地方或者去掉一個的話,只需要Add一個或者刪除一行即可。當然,現在的代碼還有很多可優化的地方,比如把通知者(LogHelper)進行抽象,還可以通過配置文件加反射再次解耦。這裏就不做過多介紹了。因爲已經星期四了...
星期四
採用Log4Net
總結
觀察者模式又叫發佈-訂閱模式,定義了一種一對多的依賴關係,讓多個觀察者同時監聽同一個對象。當對象狀態發生改變時,通知所訂閱的觀察者。
什麼時候使用?
當一個對象改變同時需要改變其他對象,並且還不知道要改變多少對象。這時應該考慮觀察者模式。