• 第三节:工厂+反射+配置文件(手写IOC)对缓存进行管理。


    一. 章前小节

     在前面的两个章节,我们运用依赖倒置原则,分别对 System.Web.Caching.Cache和 System.Runtime.Cacheing两类缓存进行了封装,并形成了ICache接口、RuntimeCacheHelp类和MemoryCacheHelp类。到这里,相当于万里长征已经走了一半,已经能面对基本的需求变更了。

         在业务层中,如果我们需要使用RuntimeCacheHelp中封装的缓存类,我们可以这样用:

         ICache iCache=new RuntimeCacheHelp()

         iCache.方法名1  、  iCache.方法名2  、 iCache.方法名3 、iCache.方法名4 。

         如果有一天,PM要求,改用MemoryCacheHelp类中的缓存,我们只需要将实例改为:

         ICache iCache=new MemoryCacheHelp()。 其它使用iCache的位置统统不需要修改。

        如果你仅仅满足于此,omg,那你的层次也太Low了,你是否想过?项目如果已经发布,我要切换缓存类型,难道我必须停止项目吗?是否有别的方式?(改配置文件?)你是否想过?一个用户每调用一次缓存相关的方法,都需要实例化一些 iCache对象?能否同一个用户保证实例唯一呢?能否所有用户保证实例唯一呢?

     以上的三个问题会在本章节和后续的几个章节陆续揭晓解决方案。

    二. 工厂+反射+配置文件(IOC)进行多类型缓存的管理

    1. 整体思路

      首先我们明确目的:我们要解决,项目发布以后,不需要停止项目,就可以切换缓存使用的类型。

      工厂:用来创建实例的地方。

      反射:不需要添加引用,动态加载程序集,可以获取程序集中的类中的方法,并进行调用。  反射详见:.Net进阶系列(2)-反射

      配置文件 : 可以将一些配置相关的信息写到app.config中,发布后可以,不需要停止项目,直接修正。

      工厂+反射+配置文件 这三者结合起来,其实就相当于IOC的原理。 IOC后面会结合Spring.Net 或 Unity进行详细介绍。

    2. 详细步骤

     (1). 新建一个CacheFactory工厂类,工厂类里有一个静态的、返回值类型为ICache、名叫CreateCacheHelp的无参方法。该方法的目的就是用来创建ICache类型的实例。

    1   public class CacheFactory
    2     {
    3         public static ICache CreateCacheHelp()
    4         {
    5           
    6             
    7         }
    8 
    9     }

        (2). 在配置文件中配置dll的名称和缓存类的名称

     <appSettings>
      <add key="ICacheDllName" value="01-CacheUtils"/>
       <!--  格式:  命名空间.类名      -->
      <add key="ICacheClassName" value="_01_CacheUtils.MemoryCacheHelp"/>     
    </appSettings>

        (3). 在工厂中读取配置文件的信息,方便反射使用。

    1     public class CacheFactory
    2      {
    3           private static string ICacheDllName = ConfigurationManager.AppSettings["ICacheDllName"];
    4           private static string ICacheClassName = ConfigurationManager.AppSettings["ICacheClassName"];
    5          public static ICache CreateCacheHelp()
    6           {
    7              Console.WriteLine("--------------------------我要创建对象了----------------------------");
    8         }
    9     }

         (4). 利用反射加载程序集,并且通过Activator.CreateInstance(type)方法来创建对象。

     public class CacheFactory
        {
            private static string ICacheDllName = ConfigurationManager.AppSettings["ICacheDllName"];
            private static string ICacheClassName = ConfigurationManager.AppSettings["ICacheClassName"];
            public static ICache CreateCacheHelp()
            {
                Console.WriteLine("--------------------------我要创建对象了----------------------------");
                Assembly assemble = Assembly.Load(ICacheDllName);
                Type type = assemble.GetType(ICacheClassName);
                //根据类型创建对象的方法
                object obj = Activator.CreateInstance(type);
                return (ICache)obj;
            }
        }

           大功告成,可以尽情的使用了?  错,截止到这一步,我们仅仅是解决了项目发布后,不需要停止停止项目,通过修改配置文件就可以更改缓存的使用类型。

           那么如果解决单线程内(单用户)内实例唯一问题呢,即创建了一次,下次不需要再创建,很多框架中都是采用CallContext数据来解决线程内实例唯一的问题(单线程)。即一次对话内CallContext中的数据共享,该次对话结束,CallContext中的数据也被销毁。

     1  public class CacheFactory
     2     {
     3         private static string ICacheDllName = ConfigurationManager.AppSettings["ICacheDllName"];
     4         private static string ICacheClassName = ConfigurationManager.AppSettings["ICacheClassName"];
     5         public static ICache CreateCacheHelp()
     6         {
     7             Console.WriteLine("--------------------------我要创建对象了----------------------------");
     8             Assembly assemble = Assembly.Load(ICacheDllName);
     9             Type type = assemble.GetType(ICacheClassName);
    10             //根据类型创建对象的方法
    11             object obj = Activator.CreateInstance(type);
    12             return (ICache)obj;
    13         }
    14 
    15         public static ICache CreateCacheHelp2()
    16         {
    17             ICache iCache = CallContext.GetData(typeof(CacheFactory).Name) as ICache;
    18             if (iCache == null)
    19             {
    20                 Console.WriteLine("--------------------------我要创建对象了----------------------------");
    21                 Assembly assemble = Assembly.Load(ICacheDllName);
    22                 Type type = assemble.GetType(ICacheClassName);
    23                 //根据类型创建对象的方法
    24                 iCache = (ICache)Activator.CreateInstance(type);
    25                 CallContext.SetData(typeof(CacheFactory).Name, iCache);
    26             }
    27             return iCache;
    28         }
    29 
    30     }

    . 简单的使用

         在这里,简单的贴一段代码,说明一下使用,后续章节,会详细测试缓存的各种用法。

     1             {
     2                 //1.模拟场景:访问数据耗时操作,用到缓存(发现只有第一次耗时,其他从缓存中读取数据都是秒读)
     3                 Console.WriteLine("------------------  1.模拟场景:访问数据耗时操作,用到缓存   ------------------------");
     4                 //ICache iCache = CacheFactory.CreateCacheHelp();
     5                 for (int i = 0; i < 5; i++)
     6                 {
     7                     ICache iCache = CacheFactory.CreateCacheHelp2();
     8                     Stopwatch stopwatch = new Stopwatch();
     9                     stopwatch.Start();
    10                     if (iCache.Contains("myData"))
    11                     {
    12                         var myData = iCache.Get<long>("myData");
    13                         Console.WriteLine("数据结果为:{0}", myData);
    14                     }
    15                     else
    16                     {
    17                         var myData = DBHelp.Query();
    18                         iCache.Add("myData", myData);
    19                         Console.WriteLine("数据结果为:{0}", myData);
    20                     }
    21                     stopwatch.Stop();
    22                     Console.WriteLine("第{0}次耗时为:{1}", i, stopwatch.ElapsedMilliseconds);
    23                 }
    24             } 
  • 相关阅读:
    codeforces round #433 div2
    bzoj1951
    bzoj3620
    bzoj2286
    bzoj1513
    bzoj4390
    codeforces round 430 div 2
    bzoj3339
    准备实现体积蒙皮
    看牛顿法的改进与验证局部收敛
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7250752.html
Copyright © 2020-2023  润新知