一. 轻车熟路

有了上一个章节对 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接口,并封装自己特有的方法。

直接上代码吧。

 /// <summary>
/// MemoryCache缓存
/// 需要引用using System.Runtime.Caching;程序集
/// 不支持缓存依赖
/// </summary>
public class MemoryCacheHelp : ICache
{ //一. 实例化的两种方式 #region 1.在属性中直接实例化MemoryCache
protected ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
#endregion #region 2.通过构造函数来实例化
//public ObjectCache Cache { get; set; }
//public MemoryCacheHelp()
//{
// Cache = MemoryCache.Default;
//}
#endregion //二. 实现接口中方法 #region 1.获取缓存的个数
/// <summary>
/// 获取缓存的个数
/// </summary>
public int Count
{
get
{
return (int)(Cache.GetCount());
}
}
#endregion #region 2.删除特定键的缓存
/// <summary>
/// 删除特定键的缓存
/// </summary>
/// <param name="key">键名</param>
public void Remove(string key)
{
Cache.Remove(key);
}
#endregion #region 3.移除全部缓存
/// <summary>
/// 移除全部缓存
/// </summary>
public void RemoveAll()
{
foreach (var item in Cache)
{
Cache.Remove(item.Key);
}
}
#endregion #region 4.根据键值获取特定类型的缓存
/// <summary>
/// 根据键值获取特定类型的缓存
/// </summary>
/// <typeparam name="T">泛型T</typeparam>
/// <param name="key">键名</param>
/// <returns></returns>
public T Get<T>(string key)
{
if (Cache.Contains(key))
{
return (T)Cache[key];
}
else
{
//此关键字对于引用类型会返回空,对于数值类型会返回零
return default(T);
}
}
#endregion #region 5.判断缓存是否存在
/// <summary>
/// 缓存是否存在
/// </summary>
/// <param name="key">键名</param>
/// <returns>true:表示存在; false:表示不存在</returns>
public bool Contains(string key)
{
return Cache.Contains(key);
}
#endregion #region 6.获取缓存值的类型(子类创建)
/// <summary>
/// 获取缓存值的类型
/// </summary>
/// <param name="key">键名</param>
/// <returns>键名对应的缓存值的类型</returns>
public Type GetCacheType(string key)
{
return Cache[key].GetType();
}
#endregion #region 7.增加或更新缓存(存在则更新,不存在则添加,采用绝对时间的模式)
/// <summary>
/// 增加或更新缓存
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="cacheTime">绝对过期时间,默认为1天</param>
public void AddOrUpdate(string key, object value, int cacheTime = )
{
if (Cache.Contains(key))
{
Cache.Remove(key);
}
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromDays(cacheTime);
Cache.Add(new CacheItem(key, value), policy);
} #endregion //三. 新增接口以外的方法 #region 1.获取全部缓存(子类创建-暂无办法实现)
public IEnumerator<KeyValuePair<string, object>> GetAllCache()
{
IEnumerator<KeyValuePair<string, object>> cacheList =null;
return cacheList;
}
#endregion #region 2.Add模式增加缓存(子类创建)
/// <summary>
/// Add模式增加缓存(如果该缓存已经存在,返回false,不存在,返回true)
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1); DateTime.Parse("2016-5-28 20:32:00");</param>
/// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
/// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
/// false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
/// </param>
/// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
/// <param name="UpdateCallback">缓存失效前的回调:含有一个参数的委托:CacheEntryUpdateArguments</param>
/// <param name="RemovedCallback">缓存失效后的回调:含有一个参数的委托:CacheEntryRemovedArguments</param>
public bool AddCache(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true,
CacheItemPriority priority = CacheItemPriority.Default, CacheEntryUpdateCallback UpdateCallback = null, CacheEntryRemovedCallback RemovedCallback = null)
{
bool flag;
CacheItemPolicy policy = new CacheItemPolicy();
policy.UpdateCallback = UpdateCallback;
policy.RemovedCallback = RemovedCallback;
policy.Priority = priority;
if (isAbsolute)
{
//绝对过期
policy.AbsoluteExpiration = absoluteExpiration;
flag = Cache.Add(key, value, policy); }
else
{
//相对过期
policy.SlidingExpiration = slidingExpiration;
flag = Cache.Add(key, value, policy); }
return flag;
}
#endregion #region 3.AddOrGetExisting模式增加缓存(子类创建)
/// <summary>
/// AddOrGetExisting模式增加缓存(如果该缓存已经存在,返回该缓存的值,不存在,执行插入操作,返回null)
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1); DateTime.Parse("2016-5-28 20:32:00");</param>
/// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
/// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
/// false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
/// </param>
/// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
/// <param name="UpdateCallback">缓存失效前的回调:含有一个参数的委托:CacheEntryUpdateArguments</param>
/// <param name="RemovedCallback">缓存失效后的回调:含有一个参数的委托:CacheEntryRemovedArguments</param>
public object AddOrGetExisting(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true,
CacheItemPriority priority = CacheItemPriority.Default, CacheEntryUpdateCallback UpdateCallback = null, CacheEntryRemovedCallback RemovedCallback = null)
{
object flag;
CacheItemPolicy policy = new CacheItemPolicy();
policy.UpdateCallback = UpdateCallback;
policy.RemovedCallback = RemovedCallback;
policy.Priority = priority;
if (isAbsolute)
{
//绝对过期
policy.AbsoluteExpiration = absoluteExpiration;
flag = Cache.AddOrGetExisting(key, value, policy); }
else
{
//相对过期
policy.SlidingExpiration = slidingExpiration;
flag = Cache.AddOrGetExisting(key, value, policy); }
return flag;
}
#endregion #region 4.Set模式增加缓存(子类创建 需要测试存在和不存在时各自对应什么情况)
/// <summary>
/// Set模式增加缓存(如果该缓存已经存在,??,不存在,??)
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1); DateTime.Parse("2016-5-28 20:32:00");</param>
/// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
/// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
/// false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
/// </param>
/// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
/// <param name="UpdateCallback">缓存失效前的回调:含有一个参数的委托:CacheEntryUpdateArguments</param>
/// <param name="RemovedCallback">缓存失效后的回调:含有一个参数的委托:CacheEntryRemovedArguments</param>
public void SetCache(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true,
CacheItemPriority priority = CacheItemPriority.Default, CacheEntryUpdateCallback UpdateCallback = null, CacheEntryRemovedCallback RemovedCallback = null)
{
CacheItemPolicy policy = new CacheItemPolicy();
policy.UpdateCallback = UpdateCallback;
policy.RemovedCallback = RemovedCallback;
policy.Priority = priority;
if (isAbsolute)
{
//绝对过期
policy.AbsoluteExpiration = absoluteExpiration;
Cache.Set(key, value, policy);
}
else
{
//相对过期
policy.SlidingExpiration = slidingExpiration;
Cache.Set(key, value, policy);
}
}
#endregion

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

第二节:从程序集的角度分析MemoryCache,并完成基本封装的更多相关文章

  1. 第一节:从程序集的角度分析System.Web.Caching.Cache ,并完成基本封装。

    一. 揭开迷雾 1. 程序集准备 a.  需要给项目添加 System.Web 程序集. b.  需要给使用的地方添加两个引用. 2. 程序集探究      在对应的类中输入关键字 Cache,选中点 ...

  2. 安全测试6_Web安全工具第二节(代理抓包分析工具)

    上节课讲了浏览器及扩展,这节课继续来学习下抓包分析. 首先看下下图,了解下代理工具的原理:代理就相当于收费站一样,任何要通过的车辆必须经过它. 浏览器的代理我们可以通过设置进行手动设置代理,或者通过P ...

  3. 第九节:从源码的角度分析MVC中的一些特性及其用法

    一. 前世今生 乍眼一看,该标题写的有点煽情,最近也是在不断反思,怎么能把博客写好,让人能读下去,通俗易懂,深入浅出. 接下来几个章节都是围绕框架本身提供特性展开,有MVC程序集提供的,也有其它程序集 ...

  4. 从虚拟机指令执行的角度分析JAVA中多态的实现原理

    从虚拟机指令执行的角度分析JAVA中多态的实现原理 前几天突然被一个"家伙"问了几个问题,其中一个是:JAVA中的多态的实现原理是什么? 我一想,这肯定不是从语法的角度来阐释多态吧 ...

  5. Android IOS WebRTC 音视频开发总结(六六)-- 三个角度分析美女视频直播这个行业

    本文主要从用户,公司和技术角度分析美女视频直播这个行业,文章最早发表在我们的微信公众号上,支持原创,详见这里, 欢迎关注微信公众号blackerteam,更多详见www.rtc.help 美女视频直播 ...

  6. 从源码的角度分析ViewGruop的事件分发

    从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View ...

  7. 从开发者的角度分析iOS应如何省电

    从开发者的角度分析iOS应如何省电 说明 网上关于iPhone如何省电的文章很多.但是基本没有讲原理.而在生活中,很多人在使用iPhone中有着明显的错误的省电习惯. 本文从iOS开发者的角度,对iO ...

  8. CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第二节

    原文链接 第二节:第一个内核 Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个国家级的实验室进行大型并 ...

  9. 从程序员的角度分析微信小程序(编程语言:用到什么学什么)

    从程序员的角度分析微信小程序(编程语言:用到什么学什么) 一.总结 一句话总结:微信小程序原理就是用JS调用底层native组件,和React Native非常类似.(需要时,用到时再学) 1.选择语 ...

随机推荐

  1. CentOS7 卸载mariadb 安装mysql的过程:

    1. 检查安装的mariadb rpm -qa |grep mariadb 得到已经安装的安装包 mariadb-libs-5.5.56-2.el7.x86_64mariadb-devel-5.5.5 ...

  2. 《Effective C#》快速笔记(一)- C# 语言习惯

    目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 is 或 as 操作符而不是强制类型转换 四.使用 Conditional ...

  3. TensorFlow中的优化算法

    搭建好网络后,常使用梯度下降类优化算法进行模型参数求解,模型越复杂我们在训练神经网络的过程上花的时间就越多,为了解决这一问题,我们就需要找一些优化算法来提高训练速度,TF的tf.train模块中提供了 ...

  4. python之count()函数

    # count()统计字符串中特定单词或短语出现次数(n = 3) strs = 'Good! Today is good day! Good job!' n = strs.lower().count ...

  5. Spark_RDD之基本RDD操作

    1.基本转化操作    1.1最常用的两个转化操作时map()和filter(). map()接收一个函数,把这个函数用于RDD中的每个元素,将函数作用之后的结果作为结果RDD中元素的值. filte ...

  6. flask再学习-思考之怎么从数据库中查询数据在页面展示!

    看别人视频觉得很简单,要自己做蒙蔽了!这样子.NO! 1. 流程: 首先要有和数据库连接的驱动!一般有PYMySQL mysqlclient 等 使用扩展Flask-SQLAlchemy 获得orm对 ...

  7. Markdown公式编辑学习笔记

    一.公式使用参考 1.如何插入公式 行中公式(放在文中与其它文字混编)可以用如下方法表示:$ 数学公式 $ 独立公式可以用如下方法表示:$$ 数学公式 $$ 自动编号的公式可以用如下方法表示: 若需要 ...

  8. 算法学习——决策单调性优化DP

    update in 2019.1.21 优化了一下文中年代久远的代码 的格式…… 什么是决策单调性? 在满足决策单调性的情况下,通常决策点会形如1111112222224444445555588888 ...

  9. 说 AppbarLayout,如何理解可折叠 Toolbar 的定制

    Material Design 是个好东西,它的出现使得 Android 也能定制高颜值的界面,并且指导了如果实现复杂炫丽的交互效果,而 android Surpport Desgin 这个支持包就是 ...

  10. luogu1712 区间 (尺取法+线段树)

    先把区间按照长度从小到大排序,然后用尺取法来做 大概就是先一点一点把区间算上 直到某个点被覆盖了m次,然后一点一点把最前面的区间扔掉,直到没有点被覆盖m次,这样反复做(相当于是它选择的区间左右端点在那 ...