第二节:从程序集的角度分析MemoryCache,并完成基本封装

一. 轻车熟路

     有了上一个章节对 System.Web.Caching.Cache 的探究,这里我们按照同样的思路对 MemoryCache 进行探究,相信必定会得心应手。

1. 程序集准备

    a. 需要给项目添加 System.Runtime.Cacheing程序集。

     b. 需要给使用的地方添加两个引用。

2. 程序集探究

 在对应的类中输入关键字 MemoryCache,选中点击F12,查看MemoryCache程序集,如下图所示:   

    细心的人会发现:MemoryCache继承了ObjectCache,那么我们在使用的时候,是不是可以考虑一下,里氏替换原则呢? 后面揭晓。

  下面我们一起来分析从上往下来分析一下该程序集。

     (1). 构造函数和属性。我们利用Default属性来代替 通过构造函数 new 来实例化对象。

  

     (2). 其他特有的新增属性。

       可用内存量、可用物理内存百分比、更新内存前等待的时间量。

    

 (3). 顾名思义通俗易懂的方法。

   a:Contains方法:根据key,来判断缓存是否存在。

         b:Get方法:根据key,来获取对应类型的缓存,通常结合泛型来封装。

         c: GetCount方法:获取缓存的个数。

         d: Remove方法:移除指定key的缓存。

 e:缓存的增加。

从程序集中可以看到,从长相貌似与增加相关的有:Add、AddOrGetExisting、Set,事实也是如此,这三类方法确实是与增加缓存相关的。

这样我们优先分析一下他们相同参数。

参数1: CacheItem item

查看CacheItem的源代码,发现实质上他就是把缓存的key和value转换成属性后的一个实体。

参数2CacheItemPolicy policy

查看CacheItemPolicy的源代码,发现该实体实体实质上就是把缓存常用的一些参数进行了封装,包括:相对过期时间、绝对过期时间、优先级、缓存失效前的回调、缓存失效后的回调

但注意:没有“缓存依赖”这个选项哦。

与System.Web.Caching.Cache 相比,相对过期时间和绝对过期时间的用法,用哪个,就设置哪个属性,另外一个忽略即可。

区分:

  A:Add方法插入: 如果插入成功,则为 true;如果缓存中已存在具有与 item 相同的键的项,则为 false。

  B:AddOrGetExisting方法: 如果存在具有相同键的缓存项,则为指定缓存项的值;否则为 null。

  C:Set方法:无返回值,至于存在相同键的情况,会是怎样呢?在后续测试章节中揭晓。

. 框架封装

   我们继续沿用上一章节中的封装思路,新建MemoryCacheHelp类,实现ICache接口,并封装自己特有的方法。

       直接上代码吧。

  1 /// <summary>
  2     /// MemoryCache缓存
  3     /// 需要引用using System.Runtime.Caching;程序集
  4     /// 不支持缓存依赖
  5     /// </summary>
  6     public class MemoryCacheHelp : ICache
  7     {
  8 
  9         //一. 实例化的两种方式
 10 
 11         #region 1.在属性中直接实例化MemoryCache
 12         protected ObjectCache Cache
 13         {
 14             get
 15             {
 16                 return MemoryCache.Default;
 17             }
 18         } 
 19         #endregion
 20 
 21         #region 2.通过构造函数来实例化
 22         //public ObjectCache Cache { get; set; }
 23         //public MemoryCacheHelp()
 24         //{
 25         //    Cache = MemoryCache.Default;
 26         //}  
 27         #endregion
 28 
 29         //二. 实现接口中方法
 30 
 31         #region 1.获取缓存的个数
 32         /// <summary>
 33         /// 获取缓存的个数
 34         /// </summary>
 35         public int Count
 36         {
 37             get
 38             {
 39                 return (int)(Cache.GetCount());
 40             }
 41         } 
 42         #endregion
 43 
 44         #region 2.删除特定键的缓存
 45         /// <summary>
 46         /// 删除特定键的缓存
 47         /// </summary>
 48         /// <param name="key">键名</param>
 49         public void Remove(string key)
 50         {
 51             Cache.Remove(key);
 52         }
 53         #endregion
 54 
 55         #region 3.移除全部缓存
 56         /// <summary>
 57         /// 移除全部缓存
 58         /// </summary>
 59         public void RemoveAll()
 60         {
 61             foreach (var item in Cache)
 62             {
 63                 Cache.Remove(item.Key);
 64             }
 65         }
 66         #endregion
 67 
 68         #region 4.根据键值获取特定类型的缓存
 69         /// <summary>
 70         /// 根据键值获取特定类型的缓存
 71         /// </summary>
 72         /// <typeparam name="T">泛型T</typeparam>
 73         /// <param name="key">键名</param>
 74         /// <returns></returns>
 75         public T Get<T>(string key)
 76         {
 77             if (Cache.Contains(key))
 78             {
 79                 return (T)Cache[key];
 80             }
 81             else
 82             {
 83                 //此关键字对于引用类型会返回空,对于数值类型会返回零
 84                 return default(T);
 85             }
 86         } 
 87         #endregion
 88 
 89         #region 5.判断缓存是否存在
 90         /// <summary>
 91         /// 缓存是否存在
 92         /// </summary>
 93         /// <param name="key">键名</param>
 94         /// <returns>true:表示存在; false:表示不存在</returns>
 95         public bool Contains(string key)
 96         {
 97             return Cache.Contains(key);
 98         }
 99         #endregion
100 
101         #region 6.获取缓存值的类型(子类创建)
102         /// <summary>
103         /// 获取缓存值的类型
104         /// </summary>
105         /// <param name="key">键名</param>
106         /// <returns>键名对应的缓存值的类型</returns>
107         public Type GetCacheType(string key)
108         {
109             return Cache[key].GetType();
110         }
111         #endregion
112 
113         #region 7.增加或更新缓存(存在则更新,不存在则添加,采用绝对时间的模式)
114         /// <summary>
115         /// 增加或更新缓存
116         /// </summary>
117         /// <param name="key"></param>
118         /// <param name="value"></param>
119         /// <param name="cacheTime">绝对过期时间,默认为1天</param>
120         public void AddOrUpdate(string key, object value, int cacheTime = 1)
121         {
122             if (Cache.Contains(key))
123             {
124                 Cache.Remove(key);
125             }
126             var policy = new CacheItemPolicy();
127             policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromDays(cacheTime);
128             Cache.Add(new CacheItem(key, value), policy);
129         }
130 
131         #endregion
132 
133 
134         //三. 新增接口以外的方法
135 
136 
137         #region 1.获取全部缓存(子类创建-暂无办法实现)
138         public IEnumerator<KeyValuePair<string, object>> GetAllCache()
139         {
140             IEnumerator<KeyValuePair<string, object>> cacheList =null;
141             return cacheList;
142         }
143         #endregion
144 
145         #region 2.Add模式增加缓存(子类创建)
146         /// <summary>
147         /// Add模式增加缓存(如果该缓存已经存在,返回false,不存在,返回true)
148         /// </summary>
149         /// <param name="key"></param>
150         /// <param name="value"></param>
151         /// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1);   DateTime.Parse("2016-5-28 20:32:00");</param>
152         /// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
153         /// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
154         ///                          false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
155         ///  </param>
156         /// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
157         ///  <param name="UpdateCallback">缓存失效前的回调:含有一个参数的委托:CacheEntryUpdateArguments</param>
158         /// <param name="RemovedCallback">缓存失效后的回调:含有一个参数的委托:CacheEntryRemovedArguments</param>
159         public bool AddCache(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true,
160             CacheItemPriority priority = CacheItemPriority.Default, CacheEntryUpdateCallback UpdateCallback = null, CacheEntryRemovedCallback RemovedCallback = null)
161         {
162             bool flag;
163             CacheItemPolicy policy = new CacheItemPolicy();
164             policy.UpdateCallback = UpdateCallback;
165             policy.RemovedCallback = RemovedCallback;
166             policy.Priority = priority;
167             if (isAbsolute)
168             {
169                 //绝对过期
170                 policy.AbsoluteExpiration = absoluteExpiration;
171                 flag = Cache.Add(key, value, policy);
172               
173             }
174             else
175             {
176                 //相对过期
177                 policy.SlidingExpiration = slidingExpiration;
178                 flag = Cache.Add(key, value, policy);
179                
180             }
181             return flag;
182         }
183         #endregion
184 
185         #region 3.AddOrGetExisting模式增加缓存(子类创建)
186         /// <summary>
187         /// AddOrGetExisting模式增加缓存(如果该缓存已经存在,返回该缓存的值,不存在,执行插入操作,返回null)
188         /// </summary>
189         /// <param name="key"></param>
190         /// <param name="value"></param>
191         /// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1);   DateTime.Parse("2016-5-28 20:32:00");</param>
192         /// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
193         /// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
194         ///                          false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
195         ///  </param>
196         /// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
197         ///  <param name="UpdateCallback">缓存失效前的回调:含有一个参数的委托:CacheEntryUpdateArguments</param>
198         /// <param name="RemovedCallback">缓存失效后的回调:含有一个参数的委托:CacheEntryRemovedArguments</param>
199         public object AddOrGetExisting(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true,
200             CacheItemPriority priority = CacheItemPriority.Default, CacheEntryUpdateCallback UpdateCallback = null, CacheEntryRemovedCallback RemovedCallback = null)
201         {
202             object flag;
203             CacheItemPolicy policy = new CacheItemPolicy();
204             policy.UpdateCallback = UpdateCallback;
205             policy.RemovedCallback = RemovedCallback;
206             policy.Priority = priority;
207             if (isAbsolute)
208             {
209                 //绝对过期
210                 policy.AbsoluteExpiration = absoluteExpiration;
211                 flag = Cache.AddOrGetExisting(key, value, policy);
212 
213             }
214             else
215             {
216                 //相对过期
217                 policy.SlidingExpiration = slidingExpiration;
218                 flag = Cache.AddOrGetExisting(key, value, policy);
219 
220             }
221             return flag;
222         }
223         #endregion
224 
225         #region 4.Set模式增加缓存(子类创建 需要测试存在和不存在时各自对应什么情况)
226         /// <summary>
227         /// Set模式增加缓存(如果该缓存已经存在,??,不存在,??)
228         /// </summary>
229         /// <param name="key"></param>
230         /// <param name="value"></param>
231         /// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1);   DateTime.Parse("2016-5-28 20:32:00");</param>
232         /// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
233         /// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
234         ///                          false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
235         ///  </param>
236         /// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
237         ///  <param name="UpdateCallback">缓存失效前的回调:含有一个参数的委托:CacheEntryUpdateArguments</param>
238         /// <param name="RemovedCallback">缓存失效后的回调:含有一个参数的委托:CacheEntryRemovedArguments</param>
239         public void SetCache(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true,
240             CacheItemPriority priority = CacheItemPriority.Default, CacheEntryUpdateCallback UpdateCallback = null, CacheEntryRemovedCallback RemovedCallback = null)
241         {
242             CacheItemPolicy policy = new CacheItemPolicy();
243             policy.UpdateCallback = UpdateCallback;
244             policy.RemovedCallback = RemovedCallback;
245             policy.Priority = priority;
246             if (isAbsolute)
247             {
248                 //绝对过期
249                 policy.AbsoluteExpiration = absoluteExpiration;
250                 Cache.Set(key, value, policy);
251             }
252             else
253             {
254                 //相对过期
255                 policy.SlidingExpiration = slidingExpiration;
256                 Cache.Set(key, value, policy);
257             }
258         }
259         #endregion

  如何使用,以及使用过程的问题,在后续章节中揭晓。

原文地址:https://www.cnblogs.com/yaopengfei/p/7248761.html