这个是老生长谈的问题,这个缓存只是个框架而已可以用来扩展自己的缓存处理类,意图不在解决实际的缓存处理,在于对设计模式的一种理解和设计。方便管理缓存的层次和使用。
一般的缓存比如web的cache 使用如:cache[name]=obj,如此这般我们发现一个构架和系统里缓存往往是分层的,比如DBHelper->[SQLHelper/AccHelper/OracelHelper/Parameter/]->[SQLParameter/AccParameter/OracleParameter/] 如此的。当然可以用名称来区别,可是多了,层次也深了,维护起来是不是也非常麻烦。如果写成 cache[DBHelper][SQLHelper][SQLParameter] 会怎样?如果要统计缓存对象,查看缓存层次又如何表示?
还是老习惯上代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;
using System.Security;
/*******************************
* CWF.CachService 框架缓存服务
* 开发者:欧阳寒玟
* 开发时间:2010-04-27
* 修改时间:2010-04-27
* ****************************/
namespace CWF.CacheService
{
/// <summary>
/// 缓存服务接口
/// 所有的缓存服务都必须继承于这里方便扩展
/// </summary>
public interface ICacheService
{
/// <summary>
/// 缓存对象
/// </summary>
/// <param name="CacheName"></param>
/// <returns></returns>
ICacheContent this[string CacheName] { get; set; }
/// <summary>
/// 缓存地图
/// </summary>
XmlElement CacheMap { get; set; }
/// <summary>
/// 确认缓存对象是否存在
/// </summary>
/// <param name="CacheName">缓存名称</param>
/// <returns></returns>
bool Excute(string CacheName);
/// <summary>
/// 添加一个缓存
/// </summary>
/// <param name="CacheName"></param>
void ADD(string CacheName);
/// <summary>
/// 移除一个缓存
/// </summary>
/// <param name="CacheName"></param>
void Remove(string CacheName);
/// <summary>
/// 获取已缓存对象的名称
/// </summary>
/// <returns></returns>
IList<string> GetNameList();
/// <summary>
/// 获取一个缓存对象
/// </summary>
/// <param name="CacheName"></param>
/// <returns></returns>
ICacheContent Get(string CacheName);
}
}
缓存服务的接口当然简单点,当然简单够用就好了。
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;
/*******************************
* CWF.CachService 框架缓存服务
* 开发者:欧阳寒玟
* 开发时间:2010-10-26
* 修改时间:2010-10-26
* 个人主页:http://www.coldwin.org
* ****************************/
namespace CWF.CacheService
{
/// <summary>
/// 缓存对象接口
/// </summary>
public interface ICacheContent
{
string Key { get; set; }
string Guid { get; set; }
object Value { get;set;}
XmlElement DocumentMap { get; set; }
void Add(string key, object value);
ICacheContent Children(string key);
T Get<T>();
T Get<T>(string key);
IList<ICacheContent> GetList();
IList<ICacheContent> GetList(string key);
ICacheContent this[string cacheName] { get; set; }
void Remove(string key);
void Remove();
}
}
两个接口就搞定了,内部通过一个hashtable或者字典来放对象,当然如果有更好的存放方法也可以推荐。
做了个简单的实例:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;
using System.Security;
/*******************************
* CWF.CachService 框架缓存服务
* 开发者:欧阳寒玟
* 开发时间:2010-10-26
* 修改时间:2010-10-26
* 个人主页:http://www.coldwin.org
* ****************************/
namespace CWF.CacheService
{
/// <summary>
/// 缓存框架
/// </summary>
public class CacheSerive:ICacheService
{
private XmlElement map;
private IDictionary<string,ICacheContent> box;
public CacheSerive()
{
XmlDocument doc = new XmlDocument();
map = doc.CreateElement("root");
map.SetAttribute("Creator","欧阳寒玟");
doc.AppendChild(map);
box = new Dictionary<string, ICacheContent>();
}
public ICacheContent this[string CacheName]
{
get
{
XmlNode node=map.SelectSingleNode(CacheName);
if (node == null || node.Attributes["Guid"] == null)
{
ADD(CacheName);
return Get(CacheName);
}
else
{
return Get(CacheName);
}
}
set
{
ICacheContent content = Get(CacheName);
content.Key = value.Key;
content.Guid = value.Guid;
content.Value = value.Value;
content.DocumentMap = value.DocumentMap;
}
}
public System.Xml.XmlElement CacheMap
{
get
{
return map;
}
set
{
map=value;
}
}
public bool Excute(string CacheName)
{
XmlNode node = map.SelectSingleNode(CacheName);
if (node == null || node.Attributes["Guid"] == null)
{
return false;
}
else
{
return box.Keys.Contains(CacheName);
}
}
public void ADD(string CacheName)
{
string guid = System.Guid.NewGuid().ToString();
XmlNode node = map.OwnerDocument.CreateNode(XmlNodeType.Element, CacheName,null);
((XmlElement)node).SetAttribute("Guid", guid);
map.AppendChild(node);
CacheContent content = new CacheContent((XmlElement)node);
box.Add(guid, content);
}
public void Remove(string CacheName)
{
XmlNode node = map.SelectSingleNode(CacheName);
if (node == null || node.Attributes["Guid"] == null) return;
map.RemoveChild(node);
box.Remove(node.Attributes["Guid"].Value);
}
public IList<string> GetNameList()
{
if (!map.HasChildNodes) return null;
List<string> list = new List<string>();
foreach (XmlNode n in map.ChildNodes)
{
if (n == null || n.Attributes["Guid"] == null) continue;
list.Add(n.Name);
}
return list;
}
public ICacheContent Get(string CacheName)
{
XmlNode node = map.SelectSingleNode(CacheName);
if (node == null || node.Attributes["Guid"] == null)
{
return null;
}
ICacheContent cache = box[node.Attributes["Guid"].Value];
return cache;
}
}
}
其中用的是xml来保存缓存的层次,做services里保存字典。
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
/*******************************
* CWF.CachService 框架缓存服务
* 开发者:欧阳寒玟
* 开发时间:2010-10-26
* 修改时间:2010-10-26
* 个人主页:http://www.coldwin.org
* ****************************/
namespace CWF.CacheService
{
/// <summary>
/// 缓存对象
/// </summary>
public class CacheContent : ICacheContent
{
private IDictionary<string, ICacheContent> objBox;
private XmlElement contentMap;
private string _key;
private string _guid;
private object _value;
/// <summary>
/// 实例化
/// </summary>
/// <param name="Element">缓存地图节点</param>
public CacheContent(System.Xml.XmlElement Element)
{
contentMap = Element;
objBox = new Dictionary<string, ICacheContent>();
}
/// <summary>
/// 获取或设置缓存键值
/// </summary>
public string Key
{
get
{
return _key;
}
set
{
_key = value;
}
}
/// <summary>
/// 获取或设置缓存标识
/// </summary>
public string Guid
{
get
{
if (_guid == null)
{
_guid = System.Guid.NewGuid().ToString();
}
return _guid;
}
set
{
_guid = value;
}
}
/// <summary>
/// 获取或设置缓存对象值
/// </summary>
public object Value
{
get
{
return _value;
}
set
{
_value = value;
}
}
/// <summary>
/// 获取或设置当前缓存对象地图
/// </summary>
public System.Xml.XmlElement DocumentMap
{
get
{
return contentMap;
}
set
{
contentMap=value;
}
}
/// <summary>
/// 添加一个缓存对象
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add(string key, object value)
{
if (contentMap == null)
{
throw new Exception("没有获取缓存地图之前禁止添加子缓存对象");
}
XmlNode node = contentMap.OwnerDocument.CreateNode(XmlNodeType.Element,key,null);
string guid=System.Guid.NewGuid().ToString();
ICacheContent Contenet = new CacheContent((XmlElement)node);
objBox.Add(guid, Contenet);
((XmlElement)node).SetAttribute("Guid", guid);
contentMap.AppendChild(node);
Contenet.Key = key;
Contenet.Guid = guid;
Contenet.Value = value;
}
/// <summary>
/// 根据key获取本节点下的一个缓存对象
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public ICacheContent Children(string key)
{
XmlNode node= contentMap.SelectSingleNode(key);
if (node == null) return null;
if (node.Attributes["Guid"] == null) return null;
return objBox[node.Attributes["Guid"].Value];
}
/// <summary>
/// 得到本节点缓存的对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Get<T>()
{
return (T)this.Value;
}
/// <summary>
/// 根据本身属性key获取一个对象集合
/// 注:本身key不能为null
/// </summary>
/// <returns></returns>
public IList<ICacheContent> GetList()
{
IList<ICacheContent> list = new List<ICacheContent>();
XmlNodeList nodelist = contentMap.ChildNodes;
if (nodelist.Count <= 0) return null;
foreach (XmlNode node in nodelist)
{
if (node.Attributes["Guid"] == null) continue;
string guid = node.Attributes["Guid"].Value;
if (!objBox.ContainsKey(guid)) continue;
ICacheContent content = objBox[guid];
//if (content.Value == null) continue;
list.Add(content);
}
return list;
}
/// <summary>
/// 获取key节点下缓存对象集合
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public IList<ICacheContent> GetList(string key)
{
IList<ICacheContent> list = new List<ICacheContent>();
XmlNodeList nodelist = contentMap.SelectNodes(key);
if (nodelist.Count <= 0) return null;
foreach (XmlNode node in nodelist)
{
if (node.Attributes["Guid"] == null) continue;
string guid = node.Attributes["Guid"].Value;
ICacheContent content = this.Children(guid);
//content.Guid = guid;
list.Add(content);
}
return list;
}
/// <summary>
/// 获取或设置一个缓存对象
/// </summary>
/// <param name="cacheName"></param>
/// <returns></returns>
public ICacheContent this[string cacheName]
{
get
{
ICacheContent content;
XmlNode node =this.DocumentMap.SelectSingleNode(cacheName);
if (node == null||node.Attributes["Guid"]==null)
{
this.Add(cacheName, null);
return Children(cacheName);
}
else
{
content = Children(cacheName);
return content;
}
}
set
{
this.Key=cacheName;
this.Guid = value.Guid;
this.Value = value.Value;
this.DocumentMap = value.DocumentMap;
}
}
/// <summary>
/// 移除一个指定的缓存对象
/// 不包括本身
/// </summary>
/// <param name="key"></param>
public void Remove(string key)
{
XmlNode node = DocumentMap.SelectSingleNode(key);
if (node.HasChildNodes)
{
foreach (XmlNode n in node.ChildNodes)
{
if(n.Attributes["Guid"]==null) continue;
string guid = n.Attributes["Guid"].Value;
objBox.Remove(guid);
}
}
if (node.Attributes["Guid"] != null)
{
string guid = node.Attributes["Guid"].Value;
objBox.Remove(guid);
}
DocumentMap.RemoveChild(node);
}
/// <summary>
/// 移除本身及以下的所有对象
/// </summary>
public void Remove()
{
if (this.Key == null) throw new Exception("this.key属性为空");
XmlNode node = DocumentMap;
if (node.HasChildNodes)
{
foreach (XmlNode n in node.ChildNodes)
{
if (n.Attributes["Guid"] == null) continue;
string guid = n.Attributes["Guid"].Value;
objBox.Remove(guid);
}
}
if (node.Attributes["Guid"] != null)
{
string guid = node.Attributes["Guid"].Value;
objBox.Remove(guid);
}
this.Value = null;
node.ParentNode.RemoveChild(node);
}
/// <summary>
/// 根据key索取子节点的一个已缓存的对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">缓存名字</param>
/// <returns></returns>
public T Get<T>(string key)
{
XmlNode node = this.DocumentMap.SelectSingleNode(key);
if(node==null||node.Attributes["Guid"]==null) return default(T);
return (T)((ICacheContent)objBox[node.Attributes["Guid"].Value]).Value;
throw new NotImplementedException();
}
}
}
缓存对象类
当然我们都知道依赖抽象,但是抽象必须依赖具体对象,那么我就采用了配置文件注入的方式把我们使用的具体对象注入到系统里,个人觉得这也是最好的办法事项灵活性,系统编译完成还是可以修改具体使用对象。
using System;
using System.Collections.Generic;
using System.Text;
using CWF.ConfigManager;
using System.Configuration;
/*******************************
* CWF.CachService 框架缓存服务
* 开发者:欧阳寒玟
* 开发时间:2010-04-27
* 修改时间:2010-04-27
* ****************************/
namespace CWF.CacheService
{
/// <summary>
/// 缓存服务类
/// </summary>
public class Cache
{
private static ICacheService cache;
private static object lockObj = new object();
private Cache()
{
ConfigManager.ConfigManager configmanage = (ConfigManager.ConfigManager)ConfigurationManager.GetSection("Framework");
CacheConfig ccfig = configmanage.getCacheConfig();
cache = (ICacheService)ccfig.getCache("SampleCache");
}
private Cache(string CacheName)
{
ConfigManager.ConfigManager configmanage = (ConfigManager.ConfigManager)ConfigurationManager.GetSection("Framework");
CacheConfig ccfig = configmanage.getCacheConfig();
cache = (ICacheService)ccfig.getCache(CacheName);
}
/// <summary>
/// 获取缓存对象
/// </summary>
/// <returns></returns>
public static ICacheService GetCahe()
{
if (cache == null)
{
lock (lockObj)
{
if (cache == null)
{
new Cache();
}
}
}
return cache;
}
/// <summary>
/// 获取缓存对象
/// </summary>
/// <returns></returns>
public static ICacheService GetCahe(string CacheName)
{
if (cache == null)
{
lock (lockObj)
{
if (cache == null)
{
new Cache(CacheName);
}
}
}
return cache;
}
}
定义了几个常用的缓存数。
/// <summary>
/// 系统缓存树
/// </summary>
public static class SysCache
{
/// <summary>
/// 数据持久层缓存
/// </summary>
public static string DBH = "DataHelpCache";
/// <summary>
/// 数据映射层
/// </summary>
public static string DHMap = "DataHelpMaping";
/// <summary>
/// 数据参数层
/// </summary>
public static string DHPram = "DataHelpParameters";
}
}
总上说的如此使用:cache[SysCache.DBH ][DHPram ][“UpdateDepartmentParameter”].value=new SQLParameter[]{};
当然也有常用的add remove 方法还有范型的 T get()方法,和parent child等对象索取。
如此完毕,欢迎板砖+鸡蛋。