📄 appcache.cs
字号:
using System;
using System.Xml;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.CompilerServices;
using Qeb.Support.Common;
namespace Qeb.Support.Cache
{
public class AppCache
{
private XmlElement m_ObjectXmlMap;
private static ICacheStrategy m_cs;
private static AppCache m_AppCache;
private XmlDocument m_RootXml = new XmlDocument();
/// <summary>
/// Private construtor, required for singleton design pattern.
/// </summary>
private AppCache()
{
//load the cache strategy object
string typeName = AppConfig.GetValue("CacheStrategy", "Qeb.Support.Cache.DefaultCacheStrategy");
Type type = Type.GetType(typeName,false);
m_cs = (ICacheStrategy)Activator.CreateInstance(type, null);
if (m_cs == null)
{
AppLog.Add(new AppError("AppCache创建策略类型不成功:" + typeName,this.GetType()));
}
//create an Xml used as a map between xml expression and object cached in the
//physical storage.
m_ObjectXmlMap = m_RootXml.CreateElement("Cache");
//build the internal xml document.
m_RootXml.AppendChild(m_ObjectXmlMap);
}
/// <summary>
/// Singlton method used to return the instance of Cache class
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.Synchronized)]
public static AppCache GetInstance()
{
if (m_AppCache == null)
{
m_AppCache = new AppCache();
}
return m_AppCache;
}
/// <summary>
/// Add the object to the underlying storage and Xml mapping document
/// </summary>
/// <param name="xpath">the hierarchical location of the object in Xml document </param>
/// <param name="o">the object to be cached</param>
public virtual void AddObject(string xpath, object o)
{
AddObject(xpath, o, false);
}
/// <summary>
///
/// </summary>
/// <param name="xpath"></param>
/// <param name="o"></param>
/// <param name="removeOldObj">removeOldObject</param>
public virtual void AddObject(string xpath, object o,bool removeOldObj)
{
if (removeOldObj)
RemoveObject(xpath);
//clear up the xpath expression
string newXpath = PrepareXpath(xpath);
int separator = newXpath.LastIndexOf("/");
//find the group name
string group = newXpath.Substring(0, separator);
//find the item name
string element = newXpath.Substring(separator + 1);
XmlNode groupNode = m_ObjectXmlMap.SelectSingleNode(group);
//determin if group is already exist?, if not, create one.
if (groupNode == null)
{
lock (this)
{
//build the xml tree
groupNode = CreateNode(group);
}
}
//get a unique key to identity of object, it is used to map
//between xml and object key used in the cache strategy
string objectId = System.Guid.NewGuid().ToString();
//create an new element and new attribute for this perticular object
XmlElement objectElement = m_ObjectXmlMap.OwnerDocument.CreateElement(element);
XmlAttribute objectAttribute = m_ObjectXmlMap.OwnerDocument.CreateAttribute("objectId");
objectAttribute.Value = objectId;
objectElement.Attributes.Append(objectAttribute);
//Add the object element to the Xml document
groupNode.AppendChild(objectElement);
//add the object to the underlying storage through cache strategy
m_cs.AddObject(objectId, o);
}
/// <summary>
/// Retrieve the cached object using its hierarchical location
/// </summary>
/// <param name="xpath">hierarchical location of the object in xml document</param>
/// <returns>cached object </returns>
public virtual object RetrieveObject(string xpath)
{
object o = null;
XmlNode node = m_ObjectXmlMap.SelectSingleNode(PrepareXpath(xpath));
//if the hierarchical location existed in the xml, retrieve the object
//otherwise, return the object as null
if (node != null)
{
string objectId = node.Attributes["objectId"].Value;
//retrieve the object through cache strategy
o = m_cs.RetrieveObject(objectId);
}
return o;
}
/// <summary>
/// Remove the object from the storage and clear the Xml assocated with
/// the object
/// </summary>
/// <param name="xpath">hierarchical locatioin of the object</param>
public virtual void RemoveObject(string xpath)
{
XmlNode result = m_ObjectXmlMap.SelectSingleNode(PrepareXpath(xpath));
if (result == null) return;
//check if the xpath refers to a group(container) or
//actual element for cached object
if (result.HasChildNodes)
{
//remove all the cached object in the hastable
//and remove all the child nodes
XmlNodeList objects = result.SelectNodes("*[@objectId]");
string objectId = "";
foreach (XmlNode node in objects)
{
objectId = node.Attributes["objectId"].Value;
node.ParentNode.RemoveChild(node);
//use cache strategy to remove the objects from the
//underlying storage
m_cs.RemoveObject(objectId);
}
}
else
{
//just remove the element node and the object associate with it
string objectId = result.Attributes["objectId"].Value;
result.ParentNode.RemoveChild(result);
m_cs.RemoveObject(objectId);
}
}
/// <summary>
/// Retrive a list of object under a hierarchical location
/// </summary>
/// <param name="xpath">hierarchical location</param>
/// <returns>an array of objects</returns>
public virtual object[] RetrieveObjectList(string xpath)
{
XmlNode group = m_ObjectXmlMap.SelectSingleNode(PrepareXpath(xpath));
XmlNodeList results = group.SelectNodes(PrepareXpath(xpath) + "/*[@objectId]");
ArrayList objects = new ArrayList();
string objectId = null;
//loop through each node and link the object in object[]
//to objects stored via cache strategy
foreach (XmlNode result in results)
{
objectId = result.Attributes["objectId"].Value;
objects.Add(m_cs.RetrieveObject(objectId));
}
//convert the ArrayList to object[]
return (object[])objects.ToArray(typeof(System.Object));
}
/// <summary>
/// CreateNode is responsible for creating the xml tree that is
/// specificed in the hierarchical location of the object.
/// </summary>
/// <param name="xpath">hierarchical location</param>
/// <returns></returns>
private XmlNode CreateNode(string xpath)
{
string[] xpathArray = xpath.Split('/');
string root = "";
XmlNode parentNode = (XmlNode)m_ObjectXmlMap;
//loop through the array of levels and create the corresponding node for each level
//skip the root node.
for (int i = 1; i < xpathArray.Length; i++)
{
XmlNode node = m_ObjectXmlMap.SelectSingleNode(root + "/" + xpathArray[i]);
// if the current location doesn't exist, build one
//otherwise set the current locaiton to the it child location
if (node == null)
{
XmlElement newElement = m_ObjectXmlMap.OwnerDocument.CreateElement(xpathArray[i]);
parentNode.AppendChild(newElement);
}
//set the new location to one level lower
root = root + "/" + xpathArray[i];
parentNode = m_ObjectXmlMap.SelectSingleNode(root);
}
return parentNode;
}
/// <summary>
/// clean up the xpath so that extra '/' is removed
/// </summary>
/// <param name="xpath">hierarchical location</param>
/// <returns></returns>
private string PrepareXpath(string xpath)
{
string[] xpathArray = xpath.Split('/');
xpath = "/Cache";
foreach (string s in xpathArray)
{
if (s != "")
{
xpath = xpath + "/" + s;
}
}
return xpath;
}
}
/// <summary>
/// the interface for cache strategy.
/// each class that is pluggable to the SAF.Cache must
/// implement this interface.
/// </summary>
public interface ICacheStrategy
{
void AddObject(string objId, object o);
void RemoveObject(string objId);
object RetrieveObject(string objId);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -