zoukankan      html  css  js  c++  java
  • 配置

    在 .NET中,一种更方便操作配置项的方法

     

    在应用程序的开发过程中,我们往往会为软件提供一些配置项,以允许软件根据配置项灵活来做事情,比如配置日志文件路径等,此外,我们还可以用配置项来为用户存储其偏好设置等。

    .NET 为我们默认提供了配置机制以及配置文件,项目中的 app.config 或者 web.config 文件(如果没有,可以添加)就是 .NET 为我们提供的配置文件。在这个配置文件中的根节点 configuration 下,创建 appSettings 节点,在此节点中,我们可以添加自定义的配置项。同时,ConfigurationManager 类提供了访问及操作此配置文件(由 Configuration 类代表)中配置的方法。需要注意的是,这个类在 System.Configuration.dll 文件中,需要将它添加到项目的引用中,才能使用。

    本文主要介绍一种更为便利的方式来访问/存储配置项,当然,它本质上是使用 ConfigurationManager 类完成的。它主要的特点是以面向对象的方式来解决此问题,更具体地说,我们创建一个类,类中包括一些属性用以表示配置项,通过访问或设置这些属性,即可得到或更新对应的配置项。

    一、实现

    首先,我们为 Configuration 类添加一个扩展方法 AddOrUpdateAppSettingItem,如下 :

    复制代码
            /// <summary>
            /// 向配置的 AppSetings 节添加(如果不存在)或更新(如果已存在)给定的 key 和 value
            /// </summary>
            /// <param name="config"></param>
            /// <param name="key"></param>
            /// <param name="value"></param>
            public static void AddOrUpdateAppSettingItem(this Configuration config, string key, string value)
            {
                if (config.AppSettings.Settings.AllKeys.Contains(key))
                {
                    config.AppSettings.Settings[key].Value = value;
                }
                else
                {
                    config.AppSettings.Settings.Add(key, value);
                }
            }
        }
    复制代码

    这个方法主要实现了向 appSettings 节点添加(配置项不存在)或更新(配置项已存在)配置,接下来我们会用到这个方法。

    接着,我们定义抽象基类 ConfigSetting,如下:

    复制代码
        public abstract class ConfigSetting
        {
            /// <summary>
            /// 配置类
            /// </summary>
            /// <param name="configuration">配置</param>
            public ConfigSetting(Configuration configuration)
            {
                Configuration = configuration;
            }
    
            /// <summary>
            /// 当前配置
            /// </summary>
            public Configuration Configuration
            {
                get;
            }
    
            /// <summary>
            /// 获取当前程序配置
            /// </summary>
            /// <param name="config"></param>
            /// <returns></returns>
            public static Configuration GetCurrentConfiguration()
            {
                return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            }
    
            /// <summary>
            /// 返回指定的配置项的值
            /// </summary>
            /// <param name="settingKey"></param>
            /// <returns></returns>
            protected virtual string GetSettingValue([CallerMemberName] string settingKey = null)
            {
                return Configuration?.AppSettings?.Settings[settingKey]?.Value;
            }
    
            /// <summary>
            /// 返回指定的配置项的值
            /// </summary>
            /// <typeparam name="T">值类型</typeparam>
            /// <param name="settingKey"></param>
            /// <returns></returns>
            protected virtual T GetSettingValue<T>([CallerMemberName] string settingKey = null)
            {
                var value = GetSettingValue(settingKey);
    
                if (string.IsNullOrWhiteSpace(value))
                {
                    return default(T);
                }
                else
                {
                    return (T)Convert.ChangeType(value, typeof(T));
                }
            }
    
            /// <summary>
            /// 为指定的配置项设置值
            /// </summary>
            /// <param name="value"></param>
            /// <param name="settingKey"></param>
            protected virtual void SetSettingValue(object value, [CallerMemberName] string settingKey = null)
            {
                Configuration.AddOrUpdateAppSettingItem(settingKey, value?.ToString());
                Configuration.Save();
            }
        }
    复制代码

    其中主要包括了一个静态方法和三个受保护的 virtual 方法,说明:

    1. 静态方法 GetCurrentConfiguration 返回当前应用的配置类;
    2. GetSettingValue 和 SetSettingValue 方法则分别负责读取、设置指定配置项的值;
    3. GetSettingValue 有两个重载,其中一个用于支持泛型;
    4. 在它们的方法签名中包括 CallerMemberName 特性,通过这个属性可以得到调用此访问的方法或属性的名称。

    然后,创建一个名为 AppConfigSetting 的类,这个类将会包括一些代表配置项的属性,并且它要继承自 ConfigSetting,如下:

    复制代码
        public class AppConfigSetting : ConfigSetting
        {
            public AppConfigSetting(Configuration configuration) : base(configuration)
            {
                
            }
    
            public DateTime InstallDateTime
            {
                get { return GetSettingValue<DateTime>(); }
                set { SetSettingValue(value); }
            }
    
            public string LogFileName
            {
                get { return GetSettingValue(); }
                set { SetSettingValue(value); }
            }
    
            public int ReadBlockSize
            {
                get { return GetSettingValue<int>(); }
                set { SetSettingValue(value); }
            }
        }
    复制代码

    说明:

    1. 可以看到我们在其中增加了三个属性。而在它们的 get 与 set 段中,调用了基类中的对应的两个方法,其中,对于非 string 类型的配置项,我们调用的是 GetSettingValue<T>。
    2. 通过我们前面提到的 CallerMemberName 特性,就可以得到这里的属性名,并得到相应的配置项,这样我们就无需硬编码。所以,这个属性名,本质上就是配置项的名称。

    这样,我们将所有要用到的配置项作为属性放到 AppConfigSetting 类中,再用操作这些属性就可以完成所有对配置项的操作了。 

    二、如何使用

    使用它,也非常简单,代码如下: 

    复制代码
                var config = ConfigSetting.GetCurrentConfiguration();
                AppConfigSetting setting = new AppConfigSetting(config);
                
                // 未设置时
                MessageBox.Show($"LogFileName: {setting.LogFileName}");
    
                // 设置后,再读取
                setting.LogFileName = "log.txt";
                MessageBox.Show($"LogFileName: {setting.LogFileName}");
    复制代码

     三、补充

    为了满足在不向 AppConfigSetting 添加配置项属性,但却又要访问/存储指定配置项的需要,我们可以在基类 ConfigSetting 中添加以下三个方法:

    复制代码
            /// <summary>
            /// 返回指定的配置项的值
            /// </summary>
            /// <param name="settingKey"></param>
            /// <returns></returns>
            public string GetSettingValueByKey(string settingKey)
            {
                return GetSettingValue(settingKey);
            }
    
            /// <summary>
            /// 返回指定的配置项的值
            /// </summary>
            /// <param name="settingKey"></param>
            /// <returns></returns>
            public T GetSettingValueByKey<T>(string settingKey)
            {
                return GetSettingValue<T>(settingKey);
            }
    
            /// <summary>
            /// 为指定的配置项设置值
            /// </summary>
            /// <param name="value"></param>
            /// <param name="settingKey"></param>
            public void SetSettingValueByKey(string settingKey, object value)
            {
                SetSettingValue(value, settingKey);
            }
    复制代码

    使用这几个方法,可以自由地访问/存储配置项,不同于上面增加属性方式的是,它需要自己传递配置项 key 作参数。

    使用:

    复制代码
                // 未设置时
                MessageBox.Show($"LogLevel: {setting.GetSettingValueByKey("LogLevel")}");
    
                // 设置后,再读取
                setting.SetSettingValueByKey("LogLevel", 5);
                MessageBox.Show($"LogLevel: {setting.GetSettingValueByKey("LogLevel")}");
    复制代码

     总结

    本文主要介绍了一种访问应用程序配置更为便利的方式,其主要思想是通过基类中 GetSettingValue/SetSettingValue 两个方法借助于 CallerMemberName 特性而得到派生类中属性的名称而操作对应的配置项。当然,这里不仅提供了一种方法,更是提供一种思路,基于此,你还可以根据实际需要来调整、扩展以满足你的实际需要。 

    源码下载

  • 相关阅读:
    编写 unix和 windows的 Scala 脚本
    4种复制文件的方式性能比较
    Cacheable key collision with DefaultKeyGenerator
    Spring Cache 介绍
    Centos提示-bash: make: command not found的解决办法
    Scala的sealed关键字
    Groupby
    scala break & continue
    Scala implicit
    Scala可变长度参数
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/8352737.html
Copyright © 2011-2022 走看看