上一篇廢話了這麼多,其實重點只有一個,我這次打算利用 CacheDependency 的機制,只要一聲令下,我想移除的 cache item 就會因為 CacheDependency 的關係自動失效,而不用很辛苦的拿著 cache key 一個一個移除。
我的想法是用 tags 的概念,建立起一套靠某個 tag 就能對應到一組 cache item,然後將它移除。開始之前先來想像一下 code 寫好長什麼樣子:
透過 tags 來控制 cache items 的範例程式
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 被移除時, 會在畫面顯示資訊:
由執行結果來看,果然被移出 cache 的都是來在 funp.com 的網址… 接著來看看程式碼中出現的 TaggingCacheDependecny 是怎麼實作的。相關的 code 如下:
TaggingCacheDependency 的實作
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
用法很簡單,當你要把任何物件放進 cache 時,只要用 TaggingCacheDependency 物件來標示它的 tag:
把物件加進 Cache, 配上 TaggingCacheDependency …
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
TaggingCacheDependency.DependencyDispose("funp.com");
結果就會如同上面的程式範例一樣,還留在 cache 的該網址下載資料,在這一瞬間通通都會被清掉…
用這種方式,是不是比拿到 key 再去呼叫 Cache.Remove( key ) 的方式簡單多了呢? 同時也能夠更快速的處理複雜的移除機制。其實運用 tagging 的方式只是一例,需要的話你也可以設計合適的 CacheDependency 類別。
以下是本篇文章的兩個附加參考檔案:
Download File - URL清單
Download File - Visual Studio 2008 Project