asp.net SAF 中緩存服務(wù)的實(shí)現(xiàn)
更新時(shí)間:2008年08月08日 21:28:49 作者:
對(duì)緩存的興趣源于張子陽(yáng)寫的一篇文章《SAF 中緩存服務(wù)的實(shí)現(xiàn)》中的一個(gè)例子:
全部代碼:
ICacheStrategy.cs
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace CacheService {
// 定義如何添加、獲取、刪除欲進(jìn)行緩存的對(duì)象
public interface ICacheStrategy {
// 添加對(duì)象
void AddItem(string key, object obj);
// 獲取對(duì)象
object GetItem(string key);
// 刪除對(duì)象
void RemoveItem(string key);
}
public class DefaultCacheStrategy : ICacheStrategy {
private Hashtable objectStore;
public DefaultCacheStrategy() {
objectStore = new Hashtable();
}
public void AddItem(string key, object obj) {
objectStore.Add(key, obj);
}
public object GetItem(string key) {
return objectStore[key];
}
public void RemoveItem(string key) {
objectStore.Remove(key);
}
}
}
Cache.cs
復(fù)制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Collections;
namespace CacheService {
// 使用樹形結(jié)構(gòu)來(lái)存儲(chǔ)對(duì)象,有別于Hashtable的平板式結(jié)構(gòu)
// 通過 XPath 來(lái)進(jìn)行對(duì)象獲取
public class Cache {
private XmlElement rootMap; // 動(dòng)態(tài)構(gòu)建的 Xml文檔 的根結(jié)點(diǎn)
private ICacheStrategy cacheStrategy;
public static readonly Cache Instance = new Cache(); // 實(shí)現(xiàn)Singleton模式
private XmlDocument doc = new XmlDocument(); // 構(gòu)建 Xml文檔
// 私有構(gòu)造函數(shù),用來(lái)實(shí)現(xiàn)Singleton模式
private Cache() {
// 這里應(yīng)用了Strategy模式。
// 改進(jìn):可以將使用何種Strategy定義到app.config中,然后使用反射來(lái)動(dòng)態(tài)創(chuàng)建類型
cacheStrategy = new DefaultCacheStrategy();
// 創(chuàng)建文檔根結(jié)點(diǎn),用于映射 實(shí)際的數(shù)據(jù)存儲(chǔ)(例如Hashtable) 和 Xml文檔
rootMap = doc.CreateElement("Cache");
// 添加根結(jié)點(diǎn)
doc.AppendChild(rootMap);
}
// 根據(jù) XPath 獲取對(duì)象
// 先根據(jù)Xpath獲得對(duì)象的Key,然后再根據(jù)Key獲取實(shí)際對(duì)象
public virtual object GetItem(string xpath) {
object obj = null;
xpath = PrepareXPath(xpath);
XmlNode node = rootMap.SelectSingleNode(xpath);
if (node != null) {
// 獲取對(duì)象的Key
string key = node.Attributes["key"].Value;
// 獲取實(shí)際對(duì)象
obj = cacheStrategy.GetItem(key);
}
return obj;
}
// 獲取一組對(duì)象,此時(shí)xpath為一個(gè)組結(jié)點(diǎn)
public virtual object[] GetList(string xpath) {
xpath = PrepareXPath(xpath);
XmlNode group = rootMap.SelectSingleNode(xpath);
// 獲取該結(jié)點(diǎn)下的所有子結(jié)點(diǎn)(使用[@key]確保子結(jié)點(diǎn)一定包含key屬性)
XmlNodeList results = group.SelectNodes(xpath + "/*[@key]");
ArrayList objects = new ArrayList();
string key;
foreach (XmlNode result in results) {
key = result.Attributes["key"].Value;
Object obj = cacheStrategy.GetItem(key);
objects.Add(obj);
}
return (object[])objects.ToArray(typeof(object));
}
// 添加對(duì)象,對(duì)象實(shí)際上還是添加到ICacheStrategy指定的存儲(chǔ)位置,
// 動(dòng)態(tài)創(chuàng)建的 Xml 結(jié)點(diǎn)僅保存了對(duì)象的Id(key),用于映射兩者間的關(guān)系
public virtual void AddItem(string xpath, object obj) {
// 獲取 Xpath,例如 /Cache/BookStore/Book/Title
string newXpath = PrepareXPath(xpath);
int separator = newXpath.LastIndexOf("/");
// 獲取組結(jié)點(diǎn)的層疊順序 ,例如 /Cache/BookStore/Book
string group = newXpath.Substring(0, separator);
// 獲取葉結(jié)點(diǎn)名稱,例如 Title
string element = newXpath.Substring(separator + 1);
// 獲取組結(jié)點(diǎn)
XmlNode groupNode = rootMap.SelectSingleNode(group);
// 如果組結(jié)點(diǎn)不存在,創(chuàng)建之
if (groupNode == null) {
lock (this) {
groupNode = CreateNode(group);
}
}
// 創(chuàng)建一個(gè)唯一的 key ,用來(lái)映射 Xml 和對(duì)象的主鍵
string key = Guid.NewGuid().ToString();
// 創(chuàng)建一個(gè)新結(jié)點(diǎn)
XmlElement objectElement = rootMap.OwnerDocument.CreateElement(element);
// 創(chuàng)建結(jié)點(diǎn)屬性 key
XmlAttribute objectAttribute = rootMap.OwnerDocument.CreateAttribute("key");
// 設(shè)置屬性值為 剛才生成的 Guid
objectAttribute.Value = key;
// 將屬性添加到結(jié)點(diǎn)
objectElement.Attributes.Append(objectAttribute);
// 將結(jié)點(diǎn)添加到 groupNode 下面(groupNode為Xpath的層次部分)
groupNode.AppendChild(objectElement);
// 將 key 和 對(duì)象添加到實(shí)際的存儲(chǔ)位置,比如Hashtable
cacheStrategy.AddItem(key, obj);
}
// 根據(jù) XPath 刪除對(duì)象
public virtual void RemoveItem(string xpath) {
xpath = PrepareXPath(xpath);
XmlNode result = rootMap.SelectSingleNode(xpath);
string key; // 對(duì)象的Id
// 如果 result 是一個(gè)組結(jié)點(diǎn)(含有子結(jié)點(diǎn))
if (result.HasChildNodes) {
// 選擇所有包含有key屬性的的結(jié)點(diǎn)
XmlNodeList nodeList = result.SelectNodes("descendant::*[@key]");
foreach (XmlNode node in nodeList) {
key = node.Attributes["key"].Value;
// 從 Xml 文檔中刪除結(jié)點(diǎn)
node.ParentNode.RemoveChild(node);
// 從實(shí)際存儲(chǔ)中刪除結(jié)點(diǎn)
cacheStrategy.RemoveItem(key);
}
} else { // 如果 result 是一個(gè)葉結(jié)點(diǎn)(不含子結(jié)點(diǎn))
key = result.Attributes["key"].Value;
result.ParentNode.RemoveChild(result);
cacheStrategy.RemoveItem(key);
}
}
// 根據(jù) XPath 創(chuàng)建一個(gè)結(jié)點(diǎn)
private XmlNode CreateNode(string xpath) {
string[] xpathArray = xpath.Split('/');
string nodePath = "";
// 父節(jié)點(diǎn)初始化
XmlNode parentNode = (XmlNode)rootMap;
// 逐層深入 XPath 各層級(jí),如果結(jié)點(diǎn)不存在則創(chuàng)建
// 比如 /DvdStore/Dvd/NoOneLivesForever
for (int i = 1; i < xpathArray.Length; i++) {
XmlNode node = rootMap.SelectSingleNode(nodePath + "/" + xpathArray[i]);
if (node == null) {
XmlElement newElement = rootMap.OwnerDocument.CreateElement(xpathArray[i]); // 創(chuàng)建結(jié)點(diǎn)
parentNode.AppendChild(newElement);
}
// 創(chuàng)建新路徑,更新父節(jié)點(diǎn),進(jìn)入下一級(jí)
nodePath = nodePath + "/" + xpathArray[i];
parentNode = rootMap.SelectSingleNode(nodePath);
}
return parentNode;
}
// 構(gòu)建 XPath,使其以 /Cache 為根結(jié)點(diǎn),并清除多于的"/"字符
private string PrepareXPath(string xpath) {
string[] xpathArray = xpath.Split('/');
xpath = "/Cache"; // 這里的名稱需與構(gòu)造函數(shù)中創(chuàng)建的根結(jié)點(diǎn)名稱對(duì)應(yīng)
foreach (string s in xpathArray) {
if (s != "") {
xpath += "/" + s;
}
}
return xpath;
}
}
}
相關(guān)文章
Excel自定義關(guān)閉按鈕實(shí)現(xiàn)代碼
這篇文章主要介紹了Excel自定義關(guān)閉按鈕實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12
.net開發(fā)微信公眾平臺(tái)實(shí)例教程
這篇文章主要介紹了.net開發(fā)微信公眾平臺(tái)的方法,對(duì)微信公眾平臺(tái)開發(fā)的原理與相應(yīng)的.net實(shí)現(xiàn)方法都做了較為詳細(xì)的講述,非常實(shí)用,需要的朋友可以參考下2014-10-10
.Net 調(diào)用存儲(chǔ)過程取到return的返回值
存儲(chǔ)過程只能返回 int 類型,如果返回一個(gè)字符串 ,將會(huì)報(bào)類型轉(zhuǎn)化錯(cuò)誤,下面以示例介紹下如何取到return的值,需要的朋友可以參考下2014-08-08
ASP.NET C#生成下拉列表樹實(shí)現(xiàn)代碼
下拉列表樹很方便且時(shí)尚的一個(gè)導(dǎo)航,貌似很多的朋友都想實(shí)現(xiàn)這樣一個(gè)列表樹,本文將滿足你們的設(shè)想,通過本文你們可以學(xué)到如何使用c#生成下拉列表樹,感興趣的你可不要錯(cuò)過了啊2013-02-02
ASP.NET數(shù)據(jù)綁定之DataList控件
這篇文章主要為大家介紹了ASP.NET數(shù)據(jù)綁定中的DataList控件,DataList控件以表的形式呈現(xiàn)數(shù)據(jù),通過該控件,您可以使用不同的布局來(lái)顯示數(shù)據(jù)記錄,對(duì)DataList控件感興趣的小伙伴們可以參考一下2016-01-01
ASP.NET Core 3.0輕量級(jí)角色API控制授權(quán)庫(kù)
這篇文章介紹了ASP.NET Core 3.0輕量級(jí)角色API控制授權(quán)庫(kù),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01
ASP.NET Core中如何實(shí)現(xiàn)重定向詳解
這篇文章主要給大家介紹了關(guān)于ASP.NET Core中如何實(shí)現(xiàn)重定向的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
用Html5與Asp.net MVC上傳多個(gè)文件的實(shí)現(xiàn)代碼
Html 5 的有一些File API,對(duì)Form表單增強(qiáng)的特性,讓我們輕松支持多文件上傳,看下面的Html片斷代碼2012-08-08
ASP.NET DataTable去掉重復(fù)行的2種方法
這篇文章主要介紹了ASP.NET DataTable去掉重復(fù)行的2種方法,本文直接給出去重代碼,需要的朋友可以參考下2015-02-02

