asp.net SAF 中缓存服务的实现第5/5页

 更新时间:2008年08月08日 21:28:49   作者:  
对缓存的兴趣源于张子阳写的一篇文章《SAF 中缓存服务的实现》中的一个例子:

全部代码:
ICacheStrategy.cs 
复制代码 代码如下:

using System;    
using System.Collections.Generic;    
using System.Text;    
using System.Collections;    

namespace CacheService {    

    // 定义如何添加、获取、删除欲进行缓存的对象    
    public interface ICacheStrategy {    

        // 添加对象    
        void AddItem(string key, object obj);    

        // 获取对象    
        object GetItem(string key);    

        // 删除对象    
        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 
复制代码 代码如下:

using System;    
using System.Collections.Generic;    
using System.Text;    
using System.Xml;    
using System.Collections;    

namespace CacheService {    

    // 使用树形结构来存储对象,有别于Hashtable的平板式结构    
    // 通过 XPath 来进行对象获取    
    public class Cache {    
        private XmlElement rootMap;             //  动态构建的 Xml文档 的根结点    
        private ICacheStrategy cacheStrategy;    
        public static readonly Cache Instance = new Cache();    // 实现Singleton模式    
        private XmlDocument doc = new XmlDocument();    // 构建 Xml文档    

        // 私有构造函数,用来实现Singleton模式    
        private Cache() {    

            // 这里应用了Strategy模式。    
            // 改进:可以将使用何种Strategy定义到app.config中,然后使用反射来动态创建类型    
            cacheStrategy = new DefaultCacheStrategy();    

            // 创建文档根结点,用于映射 实际的数据存储(例如Hashtable) 和 Xml文档    
            rootMap = doc.CreateElement("Cache");    

            // 添加根结点    
            doc.AppendChild(rootMap);    
        }    

        // 根据 XPath 获取对象    
        // 先根据Xpath获得对象的Key,然后再根据Key获取实际对象    
        public virtual object GetItem(string xpath) {    

            object obj = null;    
            xpath = PrepareXPath(xpath);    
            XmlNode node = rootMap.SelectSingleNode(xpath);    

            if (node != null) {    
                // 获取对象的Key    
                string key = node.Attributes["key"].Value;    

                // 获取实际对象    
                obj = cacheStrategy.GetItem(key);    
            }    
            return obj;    
        }    

   
        // 获取一组对象,此时xpath为一个组结点    
        public virtual object[] GetList(string xpath) {    
            xpath = PrepareXPath(xpath);    

            XmlNode group = rootMap.SelectSingleNode(xpath);    

            // 获取该结点下的所有子结点(使用[@key]确保子结点一定包含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));    
        }    

   
        // 添加对象,对象实际上还是添加到ICacheStrategy指定的存储位置,    
        // 动态创建的 Xml 结点仅保存了对象的Id(key),用于映射两者间的关系    
        public virtual void AddItem(string xpath, object obj) {    

            // 获取 Xpath,例如 /Cache/BookStore/Book/Title    
            string newXpath = PrepareXPath(xpath);    

            int separator = newXpath.LastIndexOf("/");    

            // 获取组结点的层叠顺序 ,例如 /Cache/BookStore/Book    
            string group = newXpath.Substring(0, separator);    

            // 获取叶结点名称,例如 Title    
            string element = newXpath.Substring(separator + 1);    

            // 获取组结点    
            XmlNode groupNode = rootMap.SelectSingleNode(group);    

            // 如果组结点不存在,创建之    
            if (groupNode == null) {    
                lock (this) {    
                    groupNode = CreateNode(group);    
                }    
            }    

            // 创建一个唯一的 key ,用来映射 Xml 和对象的主键    
            string key = Guid.NewGuid().ToString();    

            // 创建一个新结点    
            XmlElement objectElement = rootMap.OwnerDocument.CreateElement(element);    

            // 创建结点属性 key    
            XmlAttribute objectAttribute = rootMap.OwnerDocument.CreateAttribute("key");    

            // 设置属性值为 刚才生成的 Guid    
            objectAttribute.Value = key;    

            // 将属性添加到结点    
            objectElement.Attributes.Append(objectAttribute);    

            // 将结点添加到 groupNode 下面(groupNode为Xpath的层次部分)    
            groupNode.AppendChild(objectElement);    

            // 将 key 和 对象添加到实际的存储位置,比如Hashtable    
            cacheStrategy.AddItem(key, obj);    
        }    

   
        // 根据 XPath 删除对象    
        public virtual void RemoveItem(string xpath) {    

            xpath = PrepareXPath(xpath);    
            XmlNode result = rootMap.SelectSingleNode(xpath);    

            string key;         // 对象的Id     

            // 如果 result 是一个组结点(含有子结点)    
            if (result.HasChildNodes) {    

                // 选择所有包含有key属性的的结点    
                XmlNodeList nodeList = result.SelectNodes("descendant::*[@key]");    

                foreach (XmlNode node in nodeList) {    

                    key = node.Attributes["key"].Value;    

                    // 从 Xml 文档中删除结点    
                    node.ParentNode.RemoveChild(node);    

                    // 从实际存储中删除结点    
                    cacheStrategy.RemoveItem(key);    
                }    
            } else {        // 如果 result 是一个叶结点(不含子结点)    

                key = result.Attributes["key"].Value;    
                result.ParentNode.RemoveChild(result);    
                cacheStrategy.RemoveItem(key);    
            }    
        }    

   
        // 根据 XPath 创建一个结点    
        private XmlNode CreateNode(string xpath) {    

            string[] xpathArray = xpath.Split('/');    
            string nodePath = "";    

            // 父节点初始化    
            XmlNode parentNode = (XmlNode)rootMap;      

            // 逐层深入 XPath 各层级,如果结点不存在则创建    
            // 比如 /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]); // 创建结点    
                    parentNode.AppendChild(newElement);    
                }    

                // 创建新路径,更新父节点,进入下一级    
                nodePath = nodePath + "/" + xpathArray[i];    
                parentNode = rootMap.SelectSingleNode(nodePath);    
            }    

            return parentNode;    
        }    

        // 构建 XPath,使其以 /Cache 为根结点,并清除多于的"/"字符    
        private string PrepareXPath(string xpath) {    
            string[] xpathArray = xpath.Split('/');    
            xpath = "/Cache";       // 这里的名称需与构造函数中创建的根结点名称对应    
            foreach (string s in xpathArray) {    
                if (s != "") {    
                    xpath += "/" + s;    
                }    
            }    
            return xpath;    
        }    

    }    

相关文章

最新评论