1. 升級到 BlogEngine.NET 1.6.0.0 了!

    1.6.0.0 出來一陣子了,不過到過年才有空升級... 主要的原因只有一個,就是最近 spam comments 實在太多了 =_=,新版對於這類問題的處理比較像樣一點..

    其它改進還有 nested comments 跟其它一堆改進,就不一一列出來了,有興趣的人可到官方網站去看看。

    試了一下,升級後沒啥大問題,除了 CSS 有點走樣之外... 如果各位有發現什麼地方漏掉了,請再通知我 :D

    祝大家新年快樂 :D

    2010/02/19 BlogEngine.NET 有的沒的

  2. [設計案例] 清除Cache物件 #2. Create Custom CacheDependency

    上一篇廢話了這麼多,其實重點只有一個,我這次打算利用 CacheDependency 的機制,只要一聲令下,我想移除的 cache item 就會因為 CacheDependency 的關係自動失效,而不用很辛苦的拿著 cache key 一個一個移除。 我的想法是用 tags 的概念,建立起一套靠某個 tag 就能對應到一組 cache item,然後將它移除。開始之前先來想像一下 code 寫好長什麼樣子:

    透過 tags 來控制 cache items 的範例程式[copy code]
            static void Main(string[] args)
            {
                string[] urls = new string[] {
                    "http://columns.chicken-house.net/",
                    // 共 50 組網址... 略
                };
    
                foreach (string url in urls)
                {
                    DownloadData(new Uri(url));
                }
    
                Console.ReadLine();
                TaggingCacheDependency.DependencyDispose("funp.com");
                Console.ReadLine();
            }
    
            private static void Info(string key, object value, CacheItemRemovedReason reason)
            {
                    Console.WriteLine("Remove: {0}", key);
            }
    
            private static byte[] DownloadData(Uri sourceURL)
            {
                byte[] buffer = (byte[])HttpRuntime.Cache[sourceURL.ToString()];
    
                if (buffer == null)
                {
                    // 直接到指定網址下載。略...
                    buffer = null;
    
                    HttpRuntime.Cache.Add(
                        sourceURL.ToString(),
                        buffer,
                        new TaggingCacheDependency(sourceURL.Host, sourceURL.Scheme),
                        Cache.NoAbsoluteExpiration,
                        TimeSpan.FromSeconds(600),
                        CacheItemPriority.NotRemovable,
                        Info);
                }
    
                return buffer;
            }
        }
    
        這段 sample code 做的事很簡單,程式準備了 50 個網址清單,用 for-loop 一個一個下載。下載的 method: DownloadData(Uri sourceURL) 會先檢查 cache 是否已經有資料,沒有才真正下載 (不過下載的細節不是本篇要講的,所以就直接略過了...)。 而主程式的最後一行,則是想要把指定網站 ( funp.com ) 下載的所有資料,都從 cache 移除。為了方便觀看程式結果,我特地加上了 callback method, 當 cache item 被移除時, 會在畫面顯示資訊: image 由執行結果來看,果然被移出 cache 的都是來在 funp.com 的網址... 接著來看看程式碼中出現的 TaggingCacheDependecny 是怎麼實作的。相關的 code 如下:
    TaggingCacheDependency 的實作 [copy code]
        public class TaggingCacheDependency : CacheDependency
        {
            private static Dictionary<string, List<TaggingCacheDependency>> _lists = new Dictionary<string, List<TaggingCacheDependency>>();
    
            public TaggingCacheDependency(params string[] tags)
            {
                foreach (string tag in tags)
                {
                    if (_lists.ContainsKey(tag) == false)
                    {
                        _lists.Add(tag, new List<TaggingCacheDependency>());
                    }
                    _lists[tag].Add(this);
                }
                this.SetUtcLastModified(DateTime.MinValue);
                this.FinishInit();
            }
    
            public static void DependencyDispose(string tag)
            {
                if (_lists.ContainsKey(tag) == true)
                {
                    foreach (TaggingCacheDependency tcd in _lists[tag])
                    {
                        tcd.NotifyDependencyChanged(null, EventArgs.Empty);
                    }
                    _lists[tag].Clear();
                    _lists.Remove(tag);
                }
            }
        }
      30行不到... 其實程式很簡單,TaggingCacheDependency 繼承自 CacheDependency, 額外宣告一個靜態的 Dictionary<string, List<TaggingCacheDependency>> 來處理各個標簽及 TaggingCacheDependency 的關係,剩下的就沒什麼了。呼叫 DependencyDispose( ) 就可以通知 .NET Cache 機制,將相關的 cache item 移除。 用法很簡單,當你要把任何物件放進 cache 時,只要用 TaggingCacheDependency 物件來標示它的 tag:
    把物件加進 Cache, 配上 TaggingCacheDependency ...[copy code]
                    HttpRuntime.Cache.Add(
                        sourceURL.ToString(),
                        buffer,
                        new TaggingCacheDependency(sourceURL.Host, sourceURL.Scheme),
                        Cache.NoAbsoluteExpiration,
                        TimeSpan.FromSeconds(600),
                        CacheItemPriority.NotRemovable,
                        Info);
    在這個例子裡 (line 4), 直接在 TaggingCacheDependency 物件的 constructor 上直接標上 tags, 在此例是直接把網址的 hostname, scheme 兩個部份當作 tag, 未來就可以依照這兩種資訊直接讓 cache 裡的相關物件失效。 而要下令讓 Cache 內有標上某個 tag 的 cache item 失效,只要這行:  
    將標為 "funp.com" 的 cache item 設為失效的 cache item[copy code]
                TaggingCacheDependency.DependencyDispose("funp.com");
      結果就會如同上面的程式範例一樣,還留在 cache 的該網址下載資料,在這一瞬間通通都會被清掉...   用這種方式,是不是比拿到 key 再去呼叫 Cache.Remove( key ) 的方式簡單多了呢? 同時也能夠更快速的處理複雜的移除機制。其實運用 tagging 的方式只是一例,需要的話你也可以設計合適的 CacheDependency 類別。 以下是本篇文章的兩個附加參考檔案:
    Download File - URL清單
     

    2009/12/19 設計案例: 清除 Cache 物件 .NET C# MSDN Tips 技術隨筆 有的沒的 物件導向

  3. [設計案例] 清除Cache物件 #1. 問題與作法

    每次心裡有什麼好點子想寫出來時,第一關就卡在想不出個好標題... 想來想去的標題,怎麼看就是既不顯眼又不聳動... 果然是個老實的工程師性格 =_= ...  這次要講的,是 .NET HttpRuntime 裡提供的 Cache 物件的操作心得。這個東西我想不用我多作介紹,大家都用到爛掉了吧? 不過好用歸好用,有個老問題其實一直困擾著我很久了...

    " 我該怎麼手動的把某個物件從 cache 裡移除? "

    老實說,這問題蠻沒水準的... 老叫別人要翻 MSDN,我自己怎麼沒翻? 不不... 容我花點篇幅先說明一下問題。Cache物件,是個典型的 Dictionary 型態的應用 (雖然它沒有 implement interface: IDictionary… ), 透過 key 就可以拿到 cached item. 要從 cache 裡移除某個 item, 簡單的很,只要用 Remove 這個 method, 一行就搞定了:

    從 key 移除指定的 cache item[copy code]
       1:  HttpRuntime.Cache.Remove(“cache-key”);

    別小看這一行,實作起來障礙還不少。首先,你得額外去記著 cache key 的值。當你要移除的 cache item 有多個的時後,或是移除的 items 之間的關係有點複雜時,這些 code 就不怎麼漂亮了。下一個問題是:

    " 我該如何得知所有存在 Cache 內的 keys 有那些? "

    這個問題單純的多,那些把 intelligent sense 當購物網站的人 (平常不看文件,只會按下 . 然後挑個順眼 method 來用的人),可能這次就碰壁了... Cache 物件不像一般的 Dictionary 一樣,有提供 Keys 這樣的 property ... 它藏在 GetEnumerator 這 method 內,它會把所有的 keys 給巡一遍,你需要所有的 keys 的話,可以這樣用:

    跑過 cache 裡每一個 key[copy code]
       1:  foreach (string key in HttpRuntime.Cache) { 
       2:      // … 
       3:  }

    不過這樣的風險也是蠻高的,誰曉得你拿到 key 後的下一秒,這個 cache item 還在不在 cache 內?

     

     

     

    --------------------------------------------------------------

    本文正式開始! 哈哈,前面那一段只是廢話 + 碎碎唸,現在才是正題。前面想表達的只是,因為 cache 的不確定性 (資料隨時都會被 remove), 操作起來變的要格外小心, 即使它用起來像一般的 Dictionary 一樣。

    我舉個案例,來說明我應用 cache 的情況。假如我想實作一個簡單的 web browser, 透過網路下載資源是很慢的動作,每種 browser 都會有某種程度的 cache 機制。我們就拿 Cache 物件替代 IE 的 "temporary internet files” 目錄吧。這時很簡單,只要用 URL 當作 KEY,下載的 content 就當物件塞進去就好...

    不過事情沒那麼簡單。如果程式運作了一陣子,我想提供使用者手動清除 "部份" cache 的功能的話,那該怎麼辦? 我舉幾種情況:

    1. 從 cache 裡刪除所有從某個特定網站 (如: columns.chicken-house.net) 下載的資料
    2. 從 cache 裡刪除所有特定類型的資料 (如: content-type 為 image/jpeg 的圖檔)
    3. 從 cache 裡刪除所有透過特定 protocol (如: https) 下載的資料

    這樣的要求應該不算過份吧? 用前面提到的兩種作法,你會想哭吧 XD .. 用這些基礎,你大概只能選這幾種作法 (各位網友有好作法也記得提供一下):

    1. 自己另外管理所有下載過的 URL, 用盡各種適合的資料結構,讓你可以順利的挑出這些 match 的 key, 然後移除它。

      缺點: 都作這麼多,你乾脆自己重寫個 cache 機制好了... 何況時間一久,你管理的 key, 那些對應的資料搞不好老早就通通從 cache 裡清掉了...
    2. 聰明一點,用 regular expression … 從 GetEnumerator( ) 一筆一筆過濾出要移除的 URL, 然後清掉它...

      缺點: 這作法只會檢查還留在 cache 內的 URL,不過這樣的 cache 隨便也有成千上萬個,每次都要 looping 掃一次實在不怎麼好看... 有違處女座有潔癖的個性...

     

    這些方法 code 寫起來實在不怎麼漂亮,我就不寫 sample code 了,請各位自行想像一下寫起來的樣子。抱歉,如果你用的正好是上面的作法... 那請多包含... :D   這些都是 workable 的作法,但是看起來就是沒什麼設計感;程式可以動,不過就效能、簡潔、可讀性、美感來看,就是覺的不夠精緻 @@。跟朋友討論到這個問題時,我想到一個爛主意...

    " 用蠢方法,這些 cache item 先分好類,每一類去關聯一個檔案,設 CacheDependency … 要清掉時去 touch 一下這個檔案,一整組的物件就會自動被清出 cache 了…。”

    老實說,我覺的這是個既聰明又愚蠢的作法。聰明的是它很漂亮的解決我要如何移除某一群 item 的問題...,愚蠢的是這種單純程式內可以解決的事,竟然要繞到外面不必要的 file system I/O 動作... 而這通常是最慢的...

     

    --

    咳,寫太晚,實際的程式碼明天待續...

    2009/12/19 設計案例: 清除 Cache 物件 .NET ASP.NET C# MSDN Tips 技術隨筆 物件導向

  4. 終於突破單日 100KM 了 :D (台北 大溪)

    自從上個月,在露拍買了台二手車 (GIANT YUKON) 後,總算脫離每次都搭捷運租車來騎的日子了... 其實租車也沒什麼不好,不過租來的車子一來每次租的都不大一樣,二來都不能裝些慣用的配件... 騎起來總是不大順手,三來每次都得還車,行程多少會受限...

    買了車後,可以騎的路線就廣多了.. 上上週搭捷運,試騎了 [捷運永寧站] <----> [大溪] 的路線,還蠻好騎的,風景也棒,這次就決定從家裡出發,拼一拼從大溪來回,順便突破單日破百..

    image

    圖一: 永寧 <--> 大溪 GPS Log, 來回約 50km。感謝小熊子贊助 GPS Logger :D

    沒錯,男人就是這麼愛面子,自從上回有人留了話之後,有沒有單日破百,心裡總是覺的怪怪的... 加上沒趁機會累積一些當年勇,以後那有當年勇可以掛在嘴邊? 趁著這次小孩回娘家,天氣又正好,就來試一下...

    image

    [4.5km] 台北市淡水河三號水門 (延平門),我家到台北市河濱道,就走這裡最近了..

    因為這次拼 100km, 路上老停下來照相大概就騎不完了,加上我的 G9 被帶回外婆家了,這次用的是我老爸的相機... 不大順手就沒照太多了... 中間這段就沒特別照了。所以有些地點的照片就直接用上回拍的... 上次是大晴天,這次是陰天,一看就知道了 :D

    路線大概是這樣,到淡水河邊後,沿著淡水河右岸往南走,到華江橋牽車過橋,再往南沿著大漢溪右岸到新海橋,牽車上橋到左岸後一路騎到鶯歌..

     

    image

    [19.3km] 大漢溪左岸,快到城林橋了。

     

    image

    (上回的舊照片) 剛過城林橋..

     

    image

    [27km] 轉眼間已經到鶯歌了..

     

    image

    [28km] (上回舊照片) 鶯歌陶瓷博物館,經過了好幾次,可是都沒進去過 @_@

    image

    [28.3 km] 三鶯大橋下,鶯歌到大溪的自行車道 (2009/07 才通車)

    image

    過了三鶯大橋後,腳踏車道的風景就完全不一樣了 (Y)

    image

    過了個閘門,原來水都被關在這裡,難怪一路上大漢溪都沒什麼水...

    image

    真棒的風景,我喜歡這種有有山有水的 (Y)

     

    image

    離開溪邊,到大溪的這段路變成鄉間小逕,兩旁都是韭菜田及稻田...

    image

    [41.2km] 到大溪橋了 (這次沒照照片,拿上次的照片充數... :P)

    看看碼錶,才 41.2km, 騎回家大概連 90 都不到,更別提破百了,真是失算 @@ 看看時間還夠,回程就繞去三峽老街逛逛好了。

     

    image

    雖然公司有好幾個人住三峽,不過每個都不知道那家有名的牛角麵包是那一家… 只會跟我講我上次買錯家了 XD...

    看來還是 GOOGLE + 路人比較可靠,這次就找到了... 是在條不起眼的巷子裡,一家叫 [福美軒] 的麵包店.. 一堆人等著麵包出爐,排隊排到店外面... 足足排了一小時才買到 =_=,一個 20 元,每人限購 30 個...

    image

    在回程的路上拿了兩個出來吃,果然好吃 (Y)

     

    image

    柑園橋旁的XX公園 (抱歉,名字忘記了),有一片草地,前面的是蓮花池... 不過季節不對,看不到蓮花 @@ 那堆綠綠的是布袋蓮,可不是草地... 踩下去是會掉下去的

     

     

     

     

     

     

     

     

     

    image

    [85km] 華江橋上照的..

     

    image

    最後回到家,最後一個巷子口看了一下碼錶,98.5km…. @@

    單日破百的行程怎麼可以敗在這最後這區區 1.5km ? 於是就繞了點路,去附近的腳踏車店打個氣,然後再回家... 正好 100.29 km! 哇哈哈,單日破百的成就達成!

    2009/11/22 有的沒的 當年勇

  5. 原來在家裝 SERVER 的魔人還真不少...

    看了這一篇 (virtual pc guy’s weblog),才發現我比起來真是小 CASE ... 哈哈,看他這樣寫,正好最近升級到 2008R2,我也趁機把我的 SERVER 介紹一下好了 :D

    最早在家裡架 SERVER,可以追溯到 1997 ... 當時剛當兵,花了一些時間在看 MCSE 那堆 NT server administration 的書... 雖然後來沒去考,不過學到的東西還挺有用的。第一個想架的念頭,就是在 NT4 上面裝 RRAS,然後讓全家 (其實也只有我跟我姊而已) 共用一台 modem 撥接上網... 那時就弄起 RRAS,自己也寫了個 DCOM 的小程式,方便從我的 PC 遠端叫 NT SERVER 的 modem 撥號上網...

    接著就越用越兇了,基本的 NAT, NT domain controller, File Server, Printer Server, Fax Server, DHCP server 都是基本用途... 後來開始架網站,買了 chicken-house.net 這 domain name 後,開始加上 DNS / IIS / SQL 起來... 再來連 VPN 都弄起來後,事業就越作越大了..

    NT4 進步到 2000 時,原本的 NT domain 升級成 Active Directory, 開始覺的在家裡弄個 AD 有點過頭了,所以之後就沒再用 Domain, 只用 workgroup .. 直到現在...。每次重灌 SERVER 最頭痛的就是那堆帳號全部得重設一次,加上現在 Hyper-V 的效能很不錯,已經到了實用的階段,就重新燃起這念頭,也就是現在的配置。正式來介紹一下我的 SERVER 吧 :D

    2009/10/08 技術隨筆 敗家 有的沒的 水電工