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的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
随机推荐
- Python之路 day2 字符串函数
#Author:ersa name = "ersa" #首字母大写capitalize() print(name.capitalize()) name = "my nam ...
- MYSQL -NOSQL -handlersocket
一个MYSQL的插件,让MYSQL支持NOSQL 好处,跟MYSQL公用数据.比普通CACHE方便.普通CACHE有同步数据问题 坏处,不兼容MEMCAHE,跟MEMCAHE一样没安全控制 编译与安装 ...
- jquery异步加载json格式的数据
1.直接使用$.getJSON()方法是加载不了与静态界面同级别的本地的json后缀的文件. 2.解决办法:将json后缀的文件改为js后缀,这样就相当于加载了一个js文件. 解决办法:用$.getS ...
- at
1.这个命令对于自己建立的虚拟机很有帮助,比如你想过半个小时关机: [root@oc3408554812 ~]# at now + 30 minutesat> cd /tmp -h nowat& ...
- JS 百度地图导航
上一篇文章中我们就简单的学习了HTML5 地理定位,那么今天告诉大家我在项目中遇到的一个问题吧,就是怎么实现点击一个按钮就可以调到百度地图,并且获取到你当前的位置,并且导航到指定的地方去. 不想看步骤 ...
- PHP过滤外部链接及外部图片 添加rel="nofollow"属性
原来站内很多文章都是摘录的外部文章,文章里很多链接要么是时间久了失效了,要么就是一些测试的网址,如:http://localhost/ 之类的,链接多了的话,就形成站内很多死链接,这对SEO优化是很不 ...
- OC基础--Hello Shit
/* Foundation.h为主头文件, 主头文件中又拷贝了该工具箱中所有工具的头文件, 我们只需要导入主头文件就可以使用该工具箱中所有的工具, 避免了每次使用都要导入一个对应的头文件 工具箱的 ...
- cassandra 环境搭建
1 下载安装包 http://www.planetcassandra.org/cassandra/?dlink=http://downloads.datastax.com/community/dsc- ...
- PKU 1002解题总结
闲来无事,研究了一下PKU1002的题目,大意就是把含有字母的电话号码,转换为数字,然后再计算每个电话号码出现的次数,输出.本来蛮简单的一道题,结果折腾了好久,主要也是自己的水平太菜了,先是直接用字符 ...
- JMeter学习(十)内存溢出解决方法
使用jmeter进行压力测试时遇到一段时间后报内存溢出outfmenmory错误,导致jmeter卡死了,先尝试在jmeter.bat中增加了JVM_ARGS="-Xmx2048m -Xms ...