zoukankan      html  css  js  c++  java
  • 第一节:从程序集的角度分析System.Web.Caching.Cache ,并完成基本封装。

    一. 揭开迷雾

    1. 程序集准备

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

      

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

       

    2. 程序集探究

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

         

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

         (1). 两个字段,根据类型能看出来,一个是具体的时间点,另一个时间段,我们猜想,他们可能分别对应缓存中的绝对过期时间相对过期时间。(其实事实也是如此

      

        (2). 构造函数

           

          注意:通常我们实例化该类型的缓存,一般不直接通过构造函数实例化,我们通常使用 HttpRuntime.Cache 。我们一起来看看HttpRuntime的程序集,其中有个Cache属性,即可以通过它来获取Cache对象的实例。

         

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

       A : Count 属性,获取缓存个数。

                B : Get(string key) 方法,根据缓存的键名来获取缓存的值。

                C : Remove(string key) 方法,根据缓存的键名来删除缓存的值。

         

         (4). 深究  public IDictionaryEnumerator GetEnumerator();

         查看IDictionaryEnumerator的程序集,发现他是一个字典类型的集合,有键有值。

        

      那么问题来了,怎么遍历该字典类型的集合呢?怎么获取对应的键和值呢?F12查看 IEnumerator程序集,发现里面有一个MoveNext()方法,可以推进到集合的下一个元素。

        

        (5).  Add和Insert方法,二者都为增加缓存的方法,而且二者最多参数的那个重载参数类型完全相同。不同的是Insert有多种重载方式,而Add只有一种重载。 二者核心差异:当缓存已经存在,用Add添加会报错,但用Insert添加,会直接覆盖更新。

        下面以Add为例,一起来分析这七个参数。

        A:key: 代表缓存的键名。

        B:value:代表缓存的值,可以是任意类型。

        C:dependencies:表示缓存的依赖项,可以依赖文件、文件夹、多个文件、以及依赖数据库,如果不需要依赖时,传入参数null。

        D:absoluteExpiration:代表绝对过期时间,是个DateTime类型时间点。如果要启用绝对过期时间,那么slidingExpriation必须为:Cache.NoSlidingExpiration。    

         该参数表现形式可以是:如:DateTime.Now.AddDays(1);   DateTime.Parse("2016-5-28 20:32:00")  。

        E:slidingExpiration:代表相对过期时间,是个TimeSpan类型时间段。   如果要启用相对过期时间,那么absoluteExpiration必须为:Cache.NoAbsoluteExpiration

              该参数的表现形式可以是:: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒   。 

        F:priority:代表缓存销毁时的移除顺序,优先级低的先销毁。没有特殊要求通常使用: CacheItemPriority.Normal  即可。

        G:onRemoveCallBack:是一个无返回值具有三个参数的委托。public delegate void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason);

         当缓存过期时,调用该委托。委托的三个参数分别代表的含义为:缓存的键、缓存的值、缓存销毁的原因。

      

    . 缓存封装

     1.  封装思路

      首先我们要清楚,封装的目的是什么? 说白了,方便自己、方便别人的灵活调用;同时便于以后的代码维护,能应对需求的变更。

           通常调用的方式有两种:1. 将方法写成static静态方法,直接通过   类名.方法名  来进行调用。(该种方式偏离了面向对象的体系)

                                                   2. 将该类实例化,然后用实例化的对象调用该类中的封装方法。

                                                   3. 这里暂时不考虑 IOC的方式创建对象。

           我们试想,会有什么需求变化呢? 有一天,PM要求,所有使用System.Web.Caching.Cache缓存的地方,都要改成 MemoryCache,如果我们事先没有应对措施,我的天!数不胜数的方法中均是传入的 Cache实例,不支持MemoryCache的实例,排着改?保证你崩溃!!!!!

           上述场景,在实际开发中非常常见,解决该问题,我们通常使用DIP原则进行封装(依赖倒置原则,核心面向接口编程)

      所以我们定义一个缓存接口ICache,约束了缓存的定义的规范,然后我们再建立一个 RuntimeCacheHelp 类,对ICache进行了实现,同时也定义自己特有的方法

     2.  话不多说,直接上代码。

      接口:

     1     /// <summary>
     2     /// 定义缓存接口
     3     /// </summary>
     4     public interface ICache
     5     {
     6         //1.缓存的个数只能获取,不能设置
     7         int Count { get; }
     8         //2. 删除特定键的缓存
     9         void Remove(string key);
    10         //3.移除全部缓存
    11         void RemoveAll();
    12         //4.根据键值获取特定类型的缓存
    13         T Get<T>(string key);
    14         //5.判断缓存是否存在
    15         bool Contains(string key);
    16         //6. 获取缓存值的类型
    17         Type GetCacheType(string key);
    18         //7. 增加或更新缓存(存在则更新,不存在则添加,采用绝对时间的模式)
    19         /// <param name="cacheTime">绝对过期时间,默认1天</param>
    20         void AddOrUpdate(string key, object value,int cacheTime=1);
    21        
    22     }

      缓存帮助类:

      1 /// <summary>
      2     /// HttpRuntime缓存
      3     /// 需要引入:System.Web程序集
      4     /// 支持缓存依赖
      5     /// </summary>
      6     public class RuntimeCacheHelp : ICache
      7     {
      8         //一.实例化的两种方式
      9 
     10         #region 1.封装成属性
     11         protected Cache cache
     12         {
     13             get
     14             {
     15                 return HttpRuntime.Cache;
     16             }
     17         }
     18         #endregion
     19 
     20         #region 2.利用构造函数
     21 
     22         //public Cache cache2 { get; set; }
     23         //public RuntimeCacheHelp()
     24         //{
     25         //    cache2 = HttpRuntime.Cache;
     26         //} 
     27         #endregion
     28 
     29         //二. 实现接口中的方法
     30 
     31         #region 1.获取缓存的个数
     32         public int Count
     33         {
     34             get { return cache.Count; }
     35         }
     36         #endregion
     37 
     38         #region 2.删除特定键的缓存
     39         /// <summary>
     40         /// 删除特定键的缓存
     41         /// </summary>
     42         /// <param name="key">缓存的键名</param>
     43         public void Remove(string key)
     44         {
     45             cache.Remove(key);
     46         }
     47         #endregion
     48 
     49         #region 3.移除全部缓存
     50         /// <summary>
     51         /// 移除全部缓存
     52         /// </summary>
     53         public void RemoveAll()
     54         {
     55             IDictionaryEnumerator CacheEnum = cache.GetEnumerator();
     56             while (CacheEnum.MoveNext())
     57             {
     58                 cache.Remove(CacheEnum.Key.ToString());
     59             }
     60         }
     61 
     62         #endregion
     63 
     64         #region 4.根据键值获取特定类型的缓存
     65         /// <summary>
     66         /// 根据键值获取特定类型的缓存
     67         /// </summary>
     68         /// <typeparam name="T">泛型T</typeparam>
     69         /// <param name="key">键名</param>
     70         /// <returns></returns>
     71         public T Get<T>(string key)
     72         {
     73             //程序集中 this属性的应用
     74             if (cache[key] != null)
     75             {
     76                 return (T)cache[key];
     77             }
     78             return default(T);
     79         }
     80         #endregion
     81 
     82         #region 5.判断缓存是否存在
     83         /// <summary>
     84         /// 判断缓存是否存在
     85         /// </summary>
     86         /// <param name="key">键值</param>
     87         /// <returns>true代表存在;false代表不存在</returns>
     88         public bool Contains(string key)
     89         {
     90             return cache.Get(key) == null ? false : true;
     91         }
     92 
     93         #endregion
     94 
     95         #region 6.获取缓存值的类型(子类创建)
     96         /// <summary>
     97         /// 获取缓存值的类型
     98         /// </summary>
     99         /// <param name="key">键名</param>
    100         /// <returns>键名对应的缓存值的类型</returns>
    101         public Type GetCacheType(string key)
    102         {
    103             return cache[key].GetType();
    104         }
    105         #endregion
    106 
    107         #region 7.增加或更新缓存(存在则更新,不存在则添加,采用绝对时间的模式)
    108         /// <summary>
    109         /// 增加或更新缓存
    110         /// </summary>
    111         /// <param name="key"></param>
    112         /// <param name="value"></param>
    113         /// <param name="cacheTime">绝对过期时间,默认为1天</param>
    114         public void AddOrUpdate(string key, object value, int cacheTime = 1)
    115         {
    116             var absoluteTime = DateTime.Now + TimeSpan.FromDays(cacheTime);
    117             cache.Insert(key, value, null, absoluteTime, Cache.NoSlidingExpiration);
    118         }
    119 
    120         #endregion
    121 
    122         //三. 子类创建的新方法
    123 
    124 
    125         #region 1.获取全部缓存(子类创建)
    126         public IDictionaryEnumerator GetAllCache()
    127         {
    128             IDictionaryEnumerator cacheList = cache.GetEnumerator();
    129             //获取键值的方法
    130             //while (cacheList.MoveNext())
    131             //{
    132             //    var key = cacheList.Key.ToString();
    133             //    var value = cacheList.Value;
    134             //}
    135             return cacheList;
    136         }
    137         #endregion
    138 
    139         #region 2.Add模式增加缓存(子类创建)
    140         /// <summary>
    141         /// Add模式增加缓存(如果该缓存已经存在,再次添加会报错;Insert模式会覆盖上次)
    142         /// </summary>
    143         /// <param name="key"></param>
    144         /// <param name="value"></param>
    145         /// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1);   DateTime.Parse("2016-5-28 20:32:00");</param>
    146         /// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
    147         /// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
    148         ///                          false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
    149         ///  </param>
    150         /// <param name="dependencies">缓存依赖:可以依赖文件、文件夹、数据库表</param>
    151         /// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
    152         /// <param name="onRemoveCallback">缓存失效后的回调:含有三个参数的委托,三个参数分别为(key,value,reason) 即(缓存的键、值、失效原因)</param>
    153         public void AddCache(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true, CacheDependency dependencies = null,
    154             CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback onRemoveCallback = null)
    155         {
    156             if (isAbsolute)
    157             {
    158                 //绝对过期
    159                 cache.Add(key, value, dependencies, absoluteExpiration, Cache.NoSlidingExpiration, priority, onRemoveCallback);
    160             }
    161             else
    162             {
    163                 //相对过期
    164                 cache.Add(key, value, dependencies, Cache.NoAbsoluteExpiration, slidingExpiration, priority, onRemoveCallback);
    165             }
    166         }
    167         #endregion
    168 
    169         #region 3.Insert模式增加缓存(子类创建)
    170         /// <summary>
    171         /// Insert模式增加缓存(如果该缓存已经存在,会覆盖上次,Add模式则是报错)
    172         /// </summary>
    173         /// <param name="key"></param>
    174         /// <param name="value"></param>
    175         /// <param name="absoluteExpiration">绝对过期时间的参数:如:DateTime.Now.AddDays(1);   DateTime.Parse("2016-5-28 20:32:00");</param>
    176         /// <param name="slidingExpiration">相对过期时间的参数: 如:new TimeSpan(0,0, 0, 2) 天,小时,分钟,秒</param>
    177         /// <param name="isAbsolute">true代表使用绝对过期时间,填写absoluteExpiration参数,slidingExpiration忽略不需要填写
    178         ///                          false代表使用绝对过期时间,填写slidingExpiration 参数, absoluteExpiration忽略不需要填写
    179         ///  </param>
    180         /// <param name="dependencies">缓存依赖:可以依赖文件、文件夹、数据库表</param>
    181         /// <param name="priority">缓存销毁时的优先级,没有特别要求,使用该封装的默认即可</param>
    182         /// <param name="onRemoveCallback">缓存失效后的回调:含有三个参数的委托,三个参数分别为(key,value,reason) 即(缓存的键、值、失效原因)</param>
    183         public void InsertCache(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool isAbsolute = true, CacheDependency dependencies = null,
    184             CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback onRemoveCallback = null)
    185         {
    186             if (isAbsolute)
    187             {
    188                 //绝对过期
    189                 cache.Insert(key, value, dependencies, absoluteExpiration, Cache.NoSlidingExpiration, priority, onRemoveCallback);
    190             }
    191             else
    192             {
    193                 //相对过期
    194                 cache.Insert(key, value, dependencies, Cache.NoAbsoluteExpiration, slidingExpiration, priority, onRemoveCallback);
    195             }
    196         }
    197         #endregion

      3. 如何调用?调用过程中会存在哪些问题?我们再后续章节中进行介绍。

  • 相关阅读:
    非控制台应用程序输出信息到输出面板
    使用token实现接口权限验证
    创建虚拟目录http://localhost:1780/失败,错误:无法访问iis元数据库。您没用足够的特权访问计算机上的IIS网站
    隐藏桌面的回收站
    本地电脑与远程服务器之间不能复制粘贴解决方法
    移动端使用控制台打印 vconsole
    npm无法安装node-sass的解决方法
    远程报:这可能是由于credssp加密oracle修正
    L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误
    让一张图片居中在中间(代码片段)
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7234016.html
Copyright © 2011-2022 走看看