SOA Framework 开发使用手册
2.6.3 上下文缓存容器(ContextCacheQueueBase)
上下文缓存容器的基类,内部以Dictionary来存储缓存内容,该缓存容器区别于前两个容器,不受CacheManager的管理,而是由ContextCacheManager来统一管理,不需要缓存依赖项,也不需要定时扫描过期缓存项,该容器的生命期仅仅在当前线程(WinForm)或一次Http(Web)请求过程中有效,请求结束后,缓存容器随即释放。
2.6.3.1 自定义缓存项
与CacheQueue和ProtableCacheQueue一样,ContextCacheQueueBase可以存储任意自定义类型。
public class TestCacheItem1 { private int index; private string name; public int Index { get {return index;} set { index = value; } } public string Name { get { return name; } set { name = value; } } public TestCacheItem1(int index,string name) { this.index = index; this.name = name; } } 2.6.3.2 自定义缓存容器
定义一个装载项为上述类的缓存容器,在定义时需注意以下几点: 必须继承自MCS.Library.Caching. ContextCacheQueueBase. 必须向ContextCacheManager注册,否则无法实现缓存
由于ContextCacheManager中使用类型作为Dictionary的Key,所以必须使用单件,即保证类实例的单一性。
?《SOA Framework》 21
SOA Framework 开发使用手册
//定义一个缓存容器,此处必须为泛型封闭类,且必须继承ContextCacheQueueBase类,装载项为TestCacheItem1 public class TestContextCacheQueue:ContextCacheQueueBase
WebTest1 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string strChar = \ string[] aryChar = strChar.Split(','); for (int i = 0; i < 10; i++) { //创建一个缓存项 TestCacheItem1 item = new TestCacheItem1(i, aryChar[i]); //将缓存项添加到缓存容器,此处与CacheQueue和ProtableCacheQueue不同,不可添加缓存依赖 TestContextCacheQueue.Instance.Add(i, item); } Server.Transfer(\); } } WebTest2 protected void Page_Load(object sender, EventArgs e) { TestCacheItem1 item = null; TestContextCacheQueue.Instance.TryGetValue(5,out item); Response.Write(\+ item.Name); } ?《SOA Framework》 22
SOA Framework 开发使用手册
在这里使用两个Test页面,第一个页面将数据加载到缓存容器,并跳转至第二个页面,由第二个页面读取缓存容器。
2.7 实现原理
?
CacheItem
内含 Key,Value属性,并且持有一个DependencyBase来标记该缓存项的依赖内容,当DependencyBase过期时,DependencyBase的 HasChanged属性被标记为true。
通过CacheItem的SetChanged方法,可以强行将依赖项设置为过期。
CacheItem的创建实际上在给容器添加新缓存项时,内部构造。客户端仅需要将Key,Value,和依赖项传递给容器。
?《SOA Framework》 23
SOA Framework 开发使用手册
? CacheQueue和ProtableCacheQueue :继承自CacheQueueBase ?
CacheQueue
容器在内部维护一个字典,字典中存储CacheItem以及CacheItem的Key,在该字典内还有一个链表结构,以该链表的项来维护字典,在添加或访问CacheItem时,会将CacheItem添加或移动至链表的头部,并且当容器内CacheItem的个数,已经超过容器长度时,会自检并且删除尾部多余的CacheItem。这种容器的生命周期与应用程序相同,只有在应用程序被卸载的时候,才释放内存。
?
ProtableCacheQueue
无长度限制的缓存容器,内部使用Dictionary容器,来储存CacheItem,与CacheQueue类相比,此容器不可设置大小,但同样可以设置缓存过期依赖,并且由CacheManager统一扫描,删除缓存过期项。这种容器的生命周期与应用程序相同,只有在应用程序被卸载的时候,才释放内存。
?
CacheManager
内部维护一个静态字典类,该字典以CacheQueueBase的类型作为Key,CacheQueueBase的实例作为值,因此每个CacheQueueBase的派生类的实例,必须保持唯一性。CacheManager中包含一个线程,该线程根据配置文件中的扫描周期设置,如期的进行所有已注册容器的扫描,检查容器中CacheItem持有的DependencyBase引用的HasChanged属性,将所有属性值为true的缓存项,从所属容器中删除。如果应用程序是Win类型,则由CacheManager自动启动线程,如果为Web方式,则通过给HttpModule在Request时启动扫描线程。
?
ContextCacheQueue
上下文缓存容器的基类,内部以Dictionary来存储缓存内容,该缓存容器区别于前两个容器,不受CacheManager的管理,而是由ContextCacheManager来统一管理,不需要缓存依赖项,也不需要定时扫描过期缓存项,该容器的生命期仅仅在当前线程(WinForm)或一次Http(Web)请求过程中有效,请求结束后,缓存容器随即释放。
?
ContextCacheManager 和 ContextCacheQueue 内部定义如果应用程序是Web,则以
HttpContext.Current.Items[\存放缓存容器,如果是Winform则定义了一个线程级别的静态字典存放缓存容器。由于该管理器中的所有缓存容器的生命期只是一次Web或Win的请求过程中,所以无需定时扫描清理失效缓存
2.8 附录
2.8.1 AbsoluteTimeDependency
前面的例子已经写过了这个Dependency的用法。
AbsoluteTimeDependency dependency = new AbsoluteTimeDependency(DateTime.Now.AddSeconds(10)); ObjectCacheQueue.Instance.Add(\, \, dependency); 在这个类的构造方法中,提供绝对的过期时间即可。 这个类还有些属性:
?《SOA Framework》 24
SOA Framework 开发使用手册
public sealed class AbsoluteTimeDependency : DependencyBase { public AbsoluteTimeDependency(DateTime expiredTime) { } public DateTime ExpiredUtcTime { get { ? } } public DateTime ExpiredTime { get { ? } } } ? 提供给AbsoluteTimeDependency的过期时间,必须是本地时间。它在内部会转换为UTC时间。
2.8.2 SlidingTimeDependency
当用户一段时间没有访问Cache项时,此Dependency才会导致Cache项失效。用法如下:
SlidingTimeTimeDependency dependency = new SlidingTimeTimeDependency(TimeSpan.FromMinutes(20)); ObjectCacheQueue.Instance.Add(\, \, dependency); 通常应用的Session信息的缓存,就是这个Dependency的典型用法。
2.8.3 FileCacheDependency
基于文件改变的Cache依赖项在很多场景下都会使用到。例如,我们写了一个xml文件存放一些配置信息,为了保证性能,通常都会将Xml解析后的结果(如XmlDocument)缓存到内存中。当这个文件变化时,缓存中的内容会失效。
FileCacheDependency就是为此类需求准备的,它可以在构造时接受多个文件路径,然后监测它们的变化,一旦失效,就会使对应的Cache项失效。
具体的用法如下:
?《SOA Framework》 25