自定义配置项解析


  对现有的配置节进行扩展,使配置项拥有更丰富的选项,此时需要使用配置项解析类来帮忙。配置项解析类的作用是解析配置节节点的数据,生成对应的配置项实例。

  下面以分布式缓存 Redis 的实现为例,介绍如何解析自定义配置项。

  首先我们知道,要使用 Redis,必须配置 Redis 的主机地址、密码、默认db等等一大堆参数,你的做法可能是将它们放到 appSettings (.Net Framework) 或 appsettings.json 的某一个节点下(.Net Core)。但是使用 Fireasy 的配置,你可以在对应的配置项中进行扩展。


1、定义配置文件

  我们设定 Redis 配置的主要要素为:主机地址、密码、默认db,那么在原有的配置文件基础上进行如下的改造,即在原有的配置节点下增加子节点 config,如下所示:

  • .Net Framework 下的 app.config 或 web.config 文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="fireasy">
      <section name="cachings" type="Fireasy.Common.Caching.Configuration.CachingConfigurationSectionHandler, Fireasy.Common" />
    </sectionGroup>
  </configSections>
  <fireasy>
    <cachings>
      <caching type="demo.RedisCacheManager, demo">
        <config defaultDb="2" host="localhost">
        </config>
      </caching>
    </cachings>
  </fireasy>
</configuration>
  • .Net Core 下的 appsettings.json 文件
{
  "fireasy": {
    "cachings": {
      "settings": {
        "redis": {
          "type": "demo.RedisCacheManager, demo",
          "config": {
            "defaultDb": 2,
            "host": "localhost"
          }
        }
      }
    }
  }
}

2、建立 Redis 配置类

  参照配置文件中的结构,为 Redis 建立其特有的配置类 RedisConfigurationSetting,结构如下所示:

/// <summary>
/// Redis 的基本配置。
/// </summary>
[ConfigurationSettingParseType(typeof(RedisConfigurationSettingParser))]
public class RedisConfigurationSetting : IConfigurationSettingItem
{
    /// <summary>
    /// 获取 Redis 主机地址。
    /// </summary>
    public string Host { get; private set; }

    /// <summary>
    /// 获取或设置缺省的数据库编号。
    /// </summary>
    public int DefaultDb { get; set; }

    /// <summary>
    /// 获取或设置密码。
    /// </summary>
    public string Password { get; set; }
}

3、解析配置

  RedisConfigurationSetting 类使用了 ConfigurationSettingParseTypeAttribute 特性进行了标记,它指定了使用 RedisConfigurationSettingParser 类来解析配置项。这个类实现了 IConfigurationSettingParseHandler 接口,两个 Parse 方法分别针对 .Net Framework 的 Xml 配置文件和 .Net Core 的 IConfiguration 进行解析。如下所示:

/// <summary>
/// Redis 配置的解析处理器。
/// </summary>
public class RedisConfigurationSettingParser : IConfigurationSettingParseHandler
{
    public IConfigurationSettingItem Parse(System.Xml.XmlNode section)
    {
        var setting = new RedisConfigurationSetting();
        var configNode = section.SelectSingleNode("config");
        if (configNode != null)
        {
            setting.Host = configNode.GetAttributeValue<string>("host");
            setting.DefaultDb = configNode.GetAttributeValue("defaultDb", 0);
            setting.Password = configNode.GetAttributeValue("password");
        }

        return setting;
    }

#if NETSTANDARD
    public IConfigurationSettingItem Parse(IConfiguration configuration)
    {
        var setting = new RedisConfigurationSetting();
        var configNode = configuration.GetSection("config");
        if (configNode.Exists())
        {
            setting.Host = configNode["host"].To<string>();
            setting.DefaultDb = configNode["defaultDb"].To(0);
            setting.Password = configNode["password"];
        }

        return setting;
    }
#endif
}

4、附加配置项

  配置文件中,type 是一个 ICacheManager 接口的实现类 RedisCacheManager,它需要做以下两件事情:

  • 实现 IConfigurationSettingHostService 接口,以便管理器能够调用 Attach 方法将配置项传递给该实现类。

  • 使用 ConfigurationSettingAttribute 特性标记该实现类所使用的配置项类。

  有了配置项后,你就可以连接到 Redis 服务器了,实现 Redis 分布式缓存,主要的代码如下所示:

[ConfigurationSetting(typeof(RedisConfigurationSetting))]
public class RedisCacheManager : IConfigurationSettingHostService
{
    private RedisConfigurationSetting _setting;
        
    void IConfigurationSettingHostService.Attach(IConfigurationSettingItem setting)
    {
        _setting = (RedisConfigurationSetting)setting;
                
        //初始化 Redis 连接
    }
}

  注意初始化 Reids 连接不能在构造函数里处理,而应该放到 Attach 方法接收到配置项后再处理。