zoukankan      html  css  js  c++  java
  • [CLK Framework] CLK.Settings

    [CLK Framework] CLK.Settings - 跨平台的参数存取模块

    问题情景

    开发功能模块的时候,常常免不了有一些参数(例如ConnectionString),需要存放在Config檔(App.Config、Web.Config)。而.NET Framework也很贴心的提供System.Configuration命名空间里的类别,用来帮助开发人员简化存取Config档的开发工作。但是当功能模块的开发,是以跨平台执行为目标来做设计的时候,因为不是每个平台都允许Config档的存在,所以连带的System.Configuration命名空间里的类别,也并不支持跨平台的参考使用。

    像是开启一个可携式类别库项目(Portable Class Library),来设计横跨ASP.NET、Windows Phone两个平台的功能模块时,因为Windows Phone平台不支持Config档的存在,所以开发时无法在项目中加入System.Configuration命名空间的参考,用来存取Config档内的参数设定。

    遇到这样跨平台的功能模块开发,该如何处理跨平台的参数存取呢?

    问题情景01

    解决方案

    首先,不是每个平台都允许Config档的存在,每个平台各自拥有平台自己的参数存取功能,像是Windows Phone平台不允许的Config档的存在,但是可以透过操作IsolatedStorage来提供参数存取功能。为了切割与这些平台参数存取功能的相依性,可以套用IoC模式在功能模块上,用以建立一层参数存取接口,让跨平台功能模块单纯相依于同模块内的参数存取界面。接着再套用Adapter模式建立转接对象,来将每个平台的参数存取功能,转接成为参数存取接口的实作。这样后续就可以依照执行平台的不同,为跨平台功能模块注入不同的参数存取接口实作,用以提供不同平台上参数存取的功能。

    解决方案01

    假设,开发一个跨平台功能模块,就要对应开发一个套用Adapter模式的转接对象,来将每个平台的参数存取功能转接成为参数存取接口的实作。这样的开发流程在遇到跨平台功能模块越来越多的情况下,会发现需要开发的转接对象数量会迅速膨胀,进而成为开发人员工作上的负担。

    解决方案02

    为了简化转接对象的开发工作,可以将参数存取功能抽象化之后,建立成为一个共享的参数存取模块,并且这个共享参数存取模块同样透过套用IoC模式,来切割与平台参数存取功能之间的相依性,让这个共享参数存取模块可以跨平台使用。后续只需要为每个平台专有的参数存取功能,开发一个转接进共享参数存取模块的转接对象,就能让每个使用共享参数存取模块的跨平台功能模块,能够透过平台的参数存取功能来存取参数设定。

    解决方案03

    模块设计

    CLK.Settings是一个跨平台的参数存取模块。在开发跨平台功能模块时,使用CLK.Settings能够帮助开发人员,简化参数存取功能的开发工作。

    模块下载

    程序代码下载:由此进入GitHub后,点选右下角的「Download ZIP」按钮下载。

    (开启程序代码的时候,建议使用Visual Studio所提供的「大纲->折迭至定义」功能来折迭程序代码,以能得到较适合阅读的排版样式。)

    对象结构

    对象结构01

    • SettingContext

      • CLK.Settings模块的根节点对象。

      • 提供Locator功能(选用)。

    • SettingDictionary

      • 将ISettingRepository接口所提供的CRUD功能,转接为简单使用的Dictionary对象样式提供开发人员使用。

      • 继承自CLK.Collections.StoreDictionary

    • ISettingRepository

      • 套用IoC模式产生的边界接口。

      • 用来隔离系统与不同平台参数存取功能之间的相依性。

      • 提供参数数据进出模块边界的CRUD功能。

      • 继承自CLK.Collections.IStoreProvider

    • ConfigConnectionStringRepository

      • 继承ISettingRepository界面。

      • 转接Config文件的联机字符串存取功能,用以提供系统来存取Config文件中的联机字符串设定。

    • ConfigAppSettingRepository

      • 继承ISettingRepository界面。

      • 转接Config文件的AppSetting存取功能,用以提供系统来存取Config文件中的AppSetting设定。

    • MemorySettingRepository

      • 继承ISettingRepository界面。

      • 在内存中建立一个参数集合对象来存放参数设定,用以提供系统来存取内存中的参数设定。

    对象互动

    • 读取参数

      对象互动01

    • 列举参数

      对象互动02

    • 新增参数

      对象互动03

    • 移除参数

      对象互动04

    使用范例

    No001 - 建立模块

    在使用SettingContext对象之前,必须先取得系统所使用的SettingContext对象,在本篇中统一透过生成函式来提供SettingContext对象。例如下列范例中的生成函式,会建立一个SettingContext对象的子类别:ConfigSettingContext对象,这个ConfigSettingContext对象会转接Config文件的参数存取功能,用以提供系统来存取Config文件中的参数设定。

    • 建立模块

      static SettingContext Create()
      {
          // SettingContext
          SettingContext settingContext = new ConfigSettingContext();
      
          // Return
          return settingContext;
      }
      

    No002 - 读取参数

    • 建立模块

      static SettingContext Create()
      {
          // SettingContext
          SettingContext settingContext = new ConfigSettingContext();
      
          // Return
          return settingContext;
      }
      
    • 配置文件

      <!--AppSettings-->
      <appSettings>
        <add key="Argument01" value="AAAAAAAAAAAAA" />
        <add key="Argument02" value="BBBBBBBBBBBBB" />
        <add key="Argument03" value="CCCCCCCCCCCCC" />
      </appSettings>
      
      <!--ConnectionStrings-->
      <connectionStrings>
        <clear/>
        <add name="Database01" connectionString="Data Source=192.168.1.1;Initial Catalog=DB01;" />    
        <add name="Database02" connectionString="Data Source=192.168.2.2;Initial Catalog=DB02;" />
      </connectionStrings>  
      
    • 读取参数

      static void Main(string[] args)
      {
          // Create
          SettingContext settingContext = Program.Create();
      
          // Get
          Console.WriteLine("
      AppSettings");
          string argumentString = settingContext.AppSettings["Argument01"];
          Console.WriteLine(argumentString);
      
          Console.WriteLine("
      ConnectionStrings");
          string connectionString = settingContext.ConnectionStrings["Database01"];
          Console.WriteLine(connectionString);
      
          // End
          Console.WriteLine("
      Press enter to end...");
          Console.ReadLine();
      }
      
    • 执行结果

      使用范例02

    No003 - 列举参数

    • 建立模块

      static SettingContext Create()
      {
          // SettingContext
          SettingContext settingContext = new ConfigSettingContext();
      
          // Return
          return settingContext;
      }
      
    • 配置文件

      <!--AppSettings-->
      <appSettings>
        <add key="Argument01" value="AAAAAAAAAAAAA" />
        <add key="Argument02" value="BBBBBBBBBBBBB" />
        <add key="Argument03" value="CCCCCCCCCCCCC" />
      </appSettings>
      
      <!--ConnectionStrings-->
      <connectionStrings>
        <clear/>
        <add name="Database01" connectionString="Data Source=192.168.1.1;Initial Catalog=DB01;" />    
        <add name="Database02" connectionString="Data Source=192.168.2.2;Initial Catalog=DB02;" />
      </connectionStrings>  
      
    • 列举参数

      static void Main(string[] args)
      {
          // Create
          SettingContext settingContext = Program.Create();
      
          // List
          Console.WriteLine("
      AppSettings");
          foreach (string key in settingContext.AppSettings.Keys)
          {
              string argumentString = settingContext.AppSettings[key];
              Console.WriteLine(argumentString);
          }     
      
          Console.WriteLine("
      ConnectionStrings");
          foreach (string key in settingContext.ConnectionStrings.Keys)
          {
              string connectionString = settingContext.ConnectionStrings[key];
              Console.WriteLine(connectionString);
          }                                   
      
          // End
          Console.WriteLine("
      Press enter to end...");
          Console.ReadLine();
      }
      
    • 执行结果

      使用范例03

    No004 - 新增参数

    • 建立模块

      static SettingContext Create()
      {
          // SettingContext
          SettingContext settingContext = new ConfigSettingContext();
      
          // Return
          return settingContext;
      }
      
    • 原始配置文件

      <!--AppSettings-->
      <appSettings>
        <add key="Argument01" value="AAAAAAAAAAAAA" />
        <add key="Argument02" value="BBBBBBBBBBBBB" />
        <add key="Argument03" value="CCCCCCCCCCCCC" />
      </appSettings>
      
      <!--ConnectionStrings-->
      <connectionStrings>
        <clear/>
        <add name="Database01" connectionString="Data Source=192.168.1.1;Initial Catalog=DB01;" />    
        <add name="Database02" connectionString="Data Source=192.168.2.2;Initial Catalog=DB02;" />
      </connectionStrings>  
      
    • 新增参数

      static void Main(string[] args)
      {
          // Create
          SettingContext settingContext = Program.Create();
      
          // Set           
          settingContext.AppSettings.Add("Argument04", "DDDDDDDDDDDDD");
      
          settingContext.ConnectionStrings.Add("Database03", "Data Source=192.168.3.3;Initial Catalog=DB03");
      
          // End
          Console.WriteLine("
      Press enter to end...");
          Console.ReadLine();
      }
      
    • 结果配置文件

      <!--AppSettings-->
      <appSettings>
        <add key="Argument01" value="AAAAAAAAAAAAA" />
        <add key="Argument02" value="BBBBBBBBBBBBB" />
        <add key="Argument03" value="CCCCCCCCCCCCC" />
        <add key="Argument04" value="DDDDDDDDDDDDD" />
      </appSettings>
      
      <!--ConnectionStrings-->
      <connectionStrings>
        <clear />
        <add name="Database01" connectionString="Data Source=192.168.1.1;Initial Catalog=DB01;" />
        <add name="Database02" connectionString="Data Source=192.168.2.2;Initial Catalog=DB02;" />
        <add name="Database03" connectionString="Data Source=192.168.3.3;Initial Catalog=DB03" />
      </connectionStrings>  
      

    No005 - 移除参数

    • 建立模块

      static SettingContext Create()
      {
          // SettingContext
          SettingContext settingContext = new ConfigSettingContext();
      
          // Return
          return settingContext;
      }
      
    • 原始配置文件

      <!--AppSettings-->
      <appSettings>
        <add key="Argument01" value="AAAAAAAAAAAAA" />
        <add key="Argument02" value="BBBBBBBBBBBBB" />
        <add key="Argument03" value="CCCCCCCCCCCCC" />
      </appSettings>
      
      <!--ConnectionStrings-->
      <connectionStrings>
        <clear/>
        <add name="Database01" connectionString="Data Source=192.168.1.1;Initial Catalog=DB01;" />    
        <add name="Database02" connectionString="Data Source=192.168.2.2;Initial Catalog=DB02;" />
      </connectionStrings>  
      
    • 移除参数

      static void Main(string[] args)
      {
          // Create
          SettingContext settingContext = Program.Create();
      
          // Set           
          settingContext.AppSettings.Remove("Argument03");
      
          settingContext.ConnectionStrings.Remove("Database02");
      
          // End
          Console.WriteLine("
      Press enter to end...");
          Console.ReadLine();
      }
      
    • 结果配置文件

      <!--AppSettings-->
      <appSettings>
        <add key="Argument01" value="AAAAAAAAAAAAA" />
        <add key="Argument02" value="BBBBBBBBBBBBB" />
      </appSettings>
      
      <!--ConnectionStrings-->
      <connectionStrings>
        <clear />
        <add name="Database01" connectionString="Data Source=192.168.1.1;Initial Catalog=DB01;" />
      </connectionStrings>  
      

    No006 - 更换来源

    只要更换生成函式所提供的SettingContext对象,就可以更换系统所使用的参数设定来源。例如下列范例中的生成函式,改为会建立一个SettingContext对象的子类别:MemorySettingContext对象,这个MemorySettingContext对象,会在内存中建立一个参数集合对象来存放参数设定,用以提供系统来存取内存中的参数设定。

    (额外一提,作单元测试的时候,使用MemorySettingContext对象来取代ConfigSettingContext对象,就可以透过程序代码来提供测试用的参数设定,而不需要另外维护Config档来提供测试用的参数设定。)

    • 更换来源

      static SettingContext Create()
      {
          // AppSettingRepository
          MemorySettingRepository appSettingRepository = new MemorySettingRepository();
          appSettingRepository.Add("Argument05", "XXXXXXXXXXXXX");
          appSettingRepository.Add("Argument06", "YYYYYYYYYYYYY");
          appSettingRepository.Add("Argument07", "ZZZZZZZZZZZZZ");
      
          // ConnectionStringRepository
          MemorySettingRepository connectionStringRepository = new MemorySettingRepository();
          connectionStringRepository.Add("Database04", "Data Source=192.168.4.4;Initial Catalog=DB04;");
          connectionStringRepository.Add("Database05", "Data Source=192.168.5.5;Initial Catalog=DB05;");  
      
          // SettingContext
          SettingContext settingContext = new MemorySettingContext(appSettingRepository, connectionStringRepository);
      
          // Return
          return settingContext;
      }
      
    • 列举参数

      static void Main(string[] args)
      {
          // Create
          SettingContext settingContext = Program.Create();
      
          // List
          Console.WriteLine("
      AppSettings");
          foreach (string key in settingContext.AppSettings.Keys)
          {
              string argumentString = settingContext.AppSettings[key];
              Console.WriteLine(argumentString);
          }     
      
          Console.WriteLine("
      ConnectionStrings");
          foreach (string key in settingContext.ConnectionStrings.Keys)
          {
              string connectionString = settingContext.ConnectionStrings[key];
              Console.WriteLine(connectionString);
          }                                   
      
          // End
          Console.WriteLine("
      Press enter to end...");
          Console.ReadLine();
      }
      
    • 执行结果

      使用范例06

     

     


    期許自己~
    能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
    真正做到「以形寫神」的境界。


     

     

  • 相关阅读:
    #莫比乌斯函数,Miller-Rabin#洛谷 3653 小清新数学题
    #Dijkstra,二进制拆位#洛谷 5304 [GXOI/GZOI2019]旅行者
    #dp#洛谷 4158 [SCOI2009]粉刷匠
    #李超线段树,树链剖分#洛谷 4069 [SDOI2016]游戏
    #线段树合并#洛谷 3224 [HNOI2012]永无乡
    #主席树,dsu on tree,树上倍增#洛谷 3302 [SDOI2013]森林
    #树状数组,CDQ分治#洛谷 4390 [BOI2007]Mokia 摩基亚
    #单调队列#JZOJ 1753 锻炼身体
    #约数#洛谷 4296 [AHOI2007]密码箱
    #队列#洛谷 6033 合并果子 加强版
  • 原文地址:https://www.cnblogs.com/clark159/p/3397934.html
Copyright © 2011-2022 走看看