[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档内的参数设定。

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

解决方案

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

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

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

模块设计

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

模块下载

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

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

对象结构

  • 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界面。

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

对象互动

  • 读取参数

  • 列举参数

  • 新增参数

  • 移除参数

使用范例

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("\nAppSettings");
    string argumentString = settingContext.AppSettings["Argument01"];
    Console.WriteLine(argumentString); Console.WriteLine("\nConnectionStrings");
    string connectionString = settingContext.ConnectionStrings["Database01"];
    Console.WriteLine(connectionString); // End
    Console.WriteLine("\nPress enter to end...");
    Console.ReadLine();
    }
  • 执行结果

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("\nAppSettings");
    foreach (string key in settingContext.AppSettings.Keys)
    {
    string argumentString = settingContext.AppSettings[key];
    Console.WriteLine(argumentString);
    } Console.WriteLine("\nConnectionStrings");
    foreach (string key in settingContext.ConnectionStrings.Keys)
    {
    string connectionString = settingContext.ConnectionStrings[key];
    Console.WriteLine(connectionString);
    } // End
    Console.WriteLine("\nPress enter to end...");
    Console.ReadLine();
    }
  • 执行结果

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("\nPress 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("\nPress 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("\nAppSettings");
    foreach (string key in settingContext.AppSettings.Keys)
    {
    string argumentString = settingContext.AppSettings[key];
    Console.WriteLine(argumentString);
    } Console.WriteLine("\nConnectionStrings");
    foreach (string key in settingContext.ConnectionStrings.Keys)
    {
    string connectionString = settingContext.ConnectionStrings[key];
    Console.WriteLine(connectionString);
    } // End
    Console.WriteLine("\nPress enter to end...");
    Console.ReadLine();
    }
  • 执行结果

[CLK Framework] CLK.Settings - 跨平台的参数存取模块的更多相关文章

  1. [CLK Framework] CLK.Threading.PortableTimer - 跨平台的Timer类别

    [CLK Framework] CLK.Threading.PortableTimer - 跨平台的Timer类别 问题情景 开发应用程式的时候,免不了需要加入一些定时执行的设计,例如说:定时更新画面 ...

  2. python中处理命令行参数的模块optpars

    optpars是python中用来处理命令行参数的模块,可以自动生成程序的帮助信息,功能强大,易于使用,可以方便的生成标准的,符合Unix/Posix 规范的命令行说明.使用 add_option() ...

  3. python命令行参数解析模块argparse和docopt

    http://blog.csdn.net/pipisorry/article/details/53046471 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的o ...

  4. LEDAPS1.3.0版本移植到windows平台----HuPm参数初始化模块

    这个是2012年左右放在百度空间的,谁知百度空间关闭...转移到博客园. 最近项目用到3.1.2版本的LEDAPS,新版本的使用情况会在后续文章中慢慢丰富. LEDAPS的调用顺序是:HuPm--&g ...

  5. $命令行参数解析模块argparse的用法

    argparse是python内置的命令行参数解析模块,可以用来为程序配置功能丰富的命令行参数,方便使用,本文总结一下其基本用法. 测试脚本 把以下脚本存在argtest.py文件中: # codin ...

  6. Python命令行参数解析模块getopt使用实例

    Python命令行参数解析模块getopt使用实例 这篇文章主要介绍了Python命令行参数解析模块getopt使用实例,本文讲解了使用语法格式.短选项参数实例.长选项参数实例等内容,需要的朋友可以参 ...

  7. 十分钟使用ionic Framework开发一个跨平台移动应用

    Ionic是一个前端的框架,帮助开发人员使用HTML5, CSS3和JavaScript做出原生应用. ionic的理念类似前端开发的BootStrap,目标是封装HTML5移动跨平台开发的最佳实践. ...

  8. Robot Framework封装的关键字输入参数可以传入多个值的方法

    输入参数的最后一个参数可以是一个列表变量,通过@{列表名称}或者${列表名称}的方式实现传入多个值的场景: 或者

  9. 基于Java+HttpClient+TestNG的接口自动化测试框架(四)-------参数存取处理

    在真正开始接口测试之前,我们需要对参数的处理进行梳理.这里所说的“参数”,既包含之前在xml中的配置(我们称之为全局参数),也包含在每一条用例中书写的param.全局参数为固定不变的,而根据接口相应获 ...

随机推荐

  1. 完成端口(Completion Port)详解(转)

    手把手叫你玩转网络编程系列之三    完成端口(Completion Port)详解                                                           ...

  2. ios ZBar扫二维码奇奇怪怪的错误

    Undefined symbols for architecture armv7: "_CVPixelBufferGetHeight", referenced from: -[ZB ...

  3. Part 2: Oracle E-Business Suite on Cloud FAQ

    Running Oracle E-Business Suite on Oracle Cloud is simple, but it doesn't take too much effort to co ...

  4. coreseek 提示 client version is higher than daemon version 解决办法

    安装好coreseek,开启了服务之后,通过 sphinx php扩展去请求数据,提示:client version is higher than daemon version (client is ...

  5. zk框架window之间传值操作

    .zul中向Action传递参数: <listcell> <button label="修改" onClick="@command('edit',id= ...

  6. 【PRML读书笔记-Chapter1-Introduction】1.2 Probability Theory

    一个例子: 两个盒子: 一个红色:2个苹果,6个橘子; 一个蓝色:3个苹果,1个橘子; 如下图: 现在假设随机选取1个盒子,从中.取一个水果,观察它是属于哪一种水果之后,我们把它从原来的盒子中替换掉. ...

  7. 解决Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future:

    php 5个版本,5.2.5.3.5.4.5.5,怕跟不上时代,新的服务器直接上5.5,但是程序出现如下错误:Deprecated: mysql_connect(): The mysql extens ...

  8. ActivityGroup里面装的子Activity不执行OnActivityResult()的解决办法

    转自http://blog.csdn.net/snakewarhead/article/details/7976831 tab activity 中调用startActivityForResult 以 ...

  9. EditorWindow中手动控制焦点

    在Unity3D中制作编辑器的时候,有时候会需要手动控制界面上控件的焦点,与此相关的有三个函数都在下面的示例代码中了: public void Test() { // 给控件命名 GUI.SetNex ...

  10. Cwinux简介及用法简述

    我在我的个人博客上发表了一篇文章 Cwinux简介及用法简述 http://apprentice89.com/cwinux_introduction_and_use/