StackExchange.Redis.Extensions.Core 源码解读之 Configuration用法
前言
之前接触到Redis,然后选用了对StackExchange.Redis又一层封装的StackExchange.Redis.Extensions.Core类库。阅读源代码的过程中发现了他使用Configuration实现读取自定义配置的方法。特此学习并记录。在我们日常开发中,最常用的自定义配置读取方式莫过于如下两种方式,尤其是连接数据库。
//读取appsetting
var appSettingValue = ConfigurationManager.AppSettings["KEY"];
//读取connectionstring
var connectionValue = ConfigurationManager.ConnectionStrings["KEY"];
而在使用这个类库的时候它的配置形式是这样的:
<configSections>
<section name="redisCacheClient"
type="StackExchange.Redis.Extensions.Core.Configuration.RedisCachingSectionHandler, StackExchange.Redis.Extensions.Core" />
</configSections> <redisCacheClient allowAdmin="true" ssl="false" connectTimeout="5000" database="0" password="">
<hosts>
<add host="127.0.0.1" cachePort="6379"/>
<add host="127.0.0.1" cachePort="6380"/>
</hosts>
</redisCacheClient>
没错,就是自定义section,然后在读取section中详细的配置信息,如上述代码所示,sectionName=redisCacheClient,allowAdmin,ssl等都是它的配置信息。<hosts>节点比较特殊,它是一系列配置信息的集合。
代码解读
先看一下自定义配置接口,里面就包含了 redisCacheClient中的各种属性定义
/// <summary>
/// 自定义配置接口
/// </summary>
public interface IRedisCachingConfiguration
{
/// <summary>
/// Redis Server的服务端口配置
/// </summary>
/// <value>
/// IP地址或者服务器名称
/// </value>
RedisHostCollection RedisHosts { get; } /// <summary>
/// The strategy to use when executing server wide commands
/// </summary>
ServerEnumerationStrategy ServerEnumerationStrategy { get; } /// <summary>
/// 定义是否该连接可以使用管理员权限操作,比如flush database
/// </summary>
/// <value>
/// <c>true</c> 可以使用管理员权限; 否则, <c>false</c>.
/// </value>
bool AllowAdmin { get; } /// <summary>
/// 是否SSL安全加密
/// </summary>
/// <value>
/// <c>true</c> if is secure; otherwise, <c>false</c>.
/// </value>
bool Ssl { get; } /// <summary>
/// 连接超时时间
/// </summary>
int ConnectTimeout { get; } /// <summary>
/// 没有服务可用的时候,不会创建新连接
/// </summary>
bool AbortOnConnectFail { get; } /// <summary>
/// Database Id
/// </summary>
/// <value>
/// database的ID,默认为0
/// </value>
int Database { get; } /// <summary>
/// 密码
/// </summary>
string Password { get; }
}
我们看一下类的具体实现,首先要继承自定义的接口,还要继承ConfigurationSection,这样当我们取比如说 allowAdmin的值的时候可以在内部直接调用 this["allowAdmin"]取到值了。
/// <summary>
/// 继承自定义接口,并且继承ConfigurationSection<see cref="IRedisCachingConfiguration"/>
/// </summary>
public class RedisCachingSectionHandler : ConfigurationSection, IRedisCachingConfiguration
{ //这里就只拿allowAdmin举例,默认是string类型,那么我们就要根据自己的需求进行数据类型转换了。这里就把string类型转换为我们想要的bool类型
[ConfigurationProperty("allowAdmin")]
public bool AllowAdmin
{
get
{ bool result = false;
var config = this["allowAdmin"]; if (config != null)
{
var value = config.ToString(); if (!string.IsNullOrEmpty(value))
{
if (bool.TryParse(value, out result))
{
return result;
}
}
} return result;
}
} //其他代码
...
...
/// <summary>
/// 读取配置信息,外部调用主方法
/// </summary>
/// <returns></returns>
public static RedisCachingSectionHandler GetConfig()
{
return ConfigurationManager.GetSection("redisCacheClient") as RedisCachingSectionHandler;
}
}
下面我们在看一下元素集合的使用,单节点RedisHost代码如下:
/// <summary>
/// RedisHost的配置元素
/// </summary>
public class RedisHost : ConfigurationElement
{
/// <summary>
/// Gets the Redis host.
/// </summary>
/// <value>
///获取host节点值
/// </value>
[ConfigurationProperty("host", IsRequired = true)]
public string Host
{
get
{
return this["host"] as string;
}
} /// <summary>
/// Gets the port.
/// </summary>
/// <value>
/// 获取cachePort的值
/// </value>
[ConfigurationProperty("cachePort", IsRequired = true)]
public int CachePort
{
get
{
var config = this["cachePort"];
if (config != null)
{
var value = config.ToString(); if (!string.IsNullOrEmpty(value))
{
int result; if (int.TryParse(value, out result))
{
return result;
}
}
} throw new Exception("Redis Cahe port must be number.");
}
}
}
还需要定义一个Collection将Hosts中的内容收集起来。类似List
/// <summary>
/// Configuration Element Collection for <see cref="RedisHost"/>
/// </summary>
public class RedisHostCollection : ConfigurationElementCollection
{
/// <summary>
/// Gets or sets the <see cref="RedisHost"/> at the specified index.
/// </summary>
/// <value>
/// The <see cref="RedisHost"/>.
/// </value>
/// <param name="index">The index.</param>
/// <returns></returns>
public RedisHost this[int index]
{
//BaseGet,BaseRemoveAt,BaseAdd都是 ConfigurationElementCollection 中定义的方法
get
{
//调用BaseGet方法获取节点信息
return BaseGet(index) as RedisHost;
}
set
{
//设置的时候先删掉,在添加
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
} BaseAdd(index, value);
}
} /// <summary>
///此方法需要重写,返回一个新节点
/// </summary>
/// <returns></returns>
protected override ConfigurationElement CreateNewElement()
{
return new RedisHost();
} /// <summary>
/// 重写此方法,获取元素key
/// </summary>
/// <param name="element">元素</param>
/// <returns></returns>
protected override object GetElementKey(ConfigurationElement element)
//这里可以看到,这个key就是 Host:Port
=> $"{((RedisHost) element).Host}:{((RedisHost) element).CachePort}";
}
经过一层层的包装之后,Handler中后去Host的节点方法就很简单了。
/// <summary>
/// The host of Redis Server
/// </summary>
/// <value>
/// The ip or name
/// </value>
[ConfigurationProperty("hosts")]
public RedisHostCollection RedisHosts
=> this["hosts"] as RedisHostCollection;
我们运行程序读取一下试试:
RedisCachingSectionHandler config = RedisCachingSectionHandler.GetConfig();
Console.WriteLine("config中的allowAdmin:" + config.AllowAdmin);
Console.WriteLine("config中的ssl:" + config.Ssl);
Console.WriteLine("config中的password:" + config.Password);
Console.WriteLine("config中的database:" + config.Database);
Console.WriteLine();
Console.WriteLine("读取Host信息如下:");
foreach (RedisHost host in config.RedisHosts)
{
Console.WriteLine($"{host.Host}:{host.CachePort}");
}
Console.Read();
运行结果:

config中的信息已经正常读取到。那么我们可以用这种方式实现读取自己自定义的配置信息啦。当然,简单的配置还是直接用 <add key="key" value="value"/>
总结
微软库已经给我们提供了太多的方法,在不知情的情况下我们往往会自己去实现。多看看开源代码对自己知识的提升还有有帮助的。这不,学会了这种配置方法,我们就可使用不仅仅ConfigurationManager这个类了。
StackExchange.Redis.Extensions.Core 源码解读之 Configuration用法的更多相关文章
- spring core源码解读之ASM4用户手册翻译之一asm简介
第一章:ASM介绍 1.1 ASM动机: 程序的分析,生成,转换技术可以应用到许多场景: 1.程序分析,从简单的语法解析到完整的语义分析,可以应用在程序中找到潜在的bug,发现无用的代码,工程代码的逆 ...
- asp.net core源码飘香:Configuration组件
简介: 这是一个基础组件,是一个统一的配置模型,配置可以来源于配置文件(json文件,xml文件,ini文件),内存对象,命令行参数,系统的环境变量又或者是你自己扩展的配置源,该组件将各个配置源的数据 ...
- jvm源码解读--16 cas 用法解析
CAS的意思是campare and sweep比较交换 这个如果不用代码会比较抽象,那么在源码中进行解释 void ATTR ObjectMonitor::enter(TRAPS) { // The ...
- c# redis 操作类库推荐:StackExchange.Redis.Extensions
StackExchange是一个优秀的c# redis客户端,但是存在操作略为繁琐的弊端,为了简化操作,使用 StackExchange.Redis.Extensions成为了一个非常值得推荐的选择. ...
- Jfinal-Plugin源码解读
PS:cnxieyang@163.com/xieyang@e6yun.com 本文就Jfinal-plugin的源码进行分析和解读 Plugin继承及实现关系类图如下,常用的是Iplugin的三个集成 ...
- Jfinal启动源码解读
本文对Jfinal的启动源码做解释说明. PS:Jfinal启动容器可基于Tomcat/Jetty等web容器启动,本文基于Jetty的启动方式做启动源码的解读和分析,tomcat类似. 入口 JF ...
- JFinal的启动源码解读
本文对Jfinal的启动源码做解释说明. PS:Jfinal启动容器可基于Tomcat/Jetty等web容器启动,本文基于Jetty的启动方式做启动源码的解读和分析,tomcat类似. 入口 JF ...
- 《.NET 5.0 背锅案》第7集-大结局:捉拿真凶 StackExchange.Redis.Extensions 归案
第1集:验证 .NET 5.0 正式版 docker 镜像问题 第2集:码中的小窟窿,背后的大坑,发现重要嫌犯 EnyimMemcachedCore 第3集-剧情反转:EnyimMemcachedCo ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
随机推荐
- 'JAVAC' 不是内部或外部命令解决方法,记得要重启cmd
我们在配置完环境变量后,在命令提示框中输入javac命令时,往往会提示javac不是内部或者外部命令时怎么办呢?我们一起来解决它吧! 我们配置完java环境变量之后,在命令行输入javac按下回车键, ...
- 运行js提示库没有注册错误8002801d的解决办法
运行js提示库没有注册错误8002801d的解决办法这个错误主要是因为服务器上的windows scripts版本较低,请按下面的链接下载较高版本windows scripts 5.6并在服务器上进行 ...
- miniui设置边框的方法
if (field == "loginname") { if (record._id == 2) { e.cellHtml = ""; e.cellStyle ...
- Python之路 day1 用户登录多次被锁定
编写登陆接口: 输入用户名密码 认证成功后显示欢迎信息 输错三次后锁定 #Author:ersa import getpass,os,sys #读取账户信息到内存中 try: accounts_fil ...
- Bitmap旋转方法
最近在做一个ORC图片解析的功能,要求解析出数字 但是发现他解析只能解析横着的图片,然后我拍照的时候拍的是竖直照片,当然你也可以去旋转照相机的屏幕 但是我这里为了方便选择的是竖直拍出来 然后,旋转下咯 ...
- Linux 系统启动过程
linux启动时我们会看到许多启动信息. Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段: 内核的引导. 运行init. 系统初始化. 建立终端 . 用户登录系统. 内核引 ...
- Mac下安装Node.js
今天介绍一下Mac下Node.js的下载安装方法,后面我们安装Bootstrap.Angurlar和jQuery等都是通过Node.js的npm方式的. 1.在必应中搜索“node.js mac”,第 ...
- python窗体——pyqt初体验
连续两周留作业要写ftp的作业,从第一周就想实现一个窗体版本的,但是时间实在太短,qt零基础选手表示压力很大,幸好又延长了一周时间,所以也就有了今天这篇文章...只是为了介绍一些速成的方法,还有初学者 ...
- DES MAC PIN HEX
/* void DesEncrypt( UCHAR * auchInput,UCHAR * auchKey,UCHAR * auchOutput=NULL); Function: DesEncrypt ...
- leetcode算法思想快速一览
整理了一下思路,想深入了解还得多去写,无奈时间紧迫的情况下抛砖引玉也不失为下策: 1.Two Sum Easy 给出一个数组,找出其中两个和为目标值的坐标.思路: [1]排序. 和为目标值,一般的思路 ...