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的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
随机推荐
- Java与mysql数据库编程中遇见“Before start of result set at com.mysql.jdbc.SQLError.createSQLException” 的解决办法
这个Bug是因为在取出ResultSet对象,对其进行操作时,没有采用.next()方法将ResultSet对象的光标移至指定行,不管Statement对象执行SQL语句是否十分确定能搜出记录,也不可 ...
- 使用WIC组件转换图片格式
#include <windows.h>#include <Wincodec.h>#pragma comment(lib, "Windowscodecs.lib&qu ...
- WCF初探-19:WCF消息协定
WCF消息协定概述 在生成 WCF应用程序时,开发人员通常会密切关注数据结构和序列化问题,而不必关心携带数据的消息结构. 对于这些应用程序,为参数或返回值创建数据协定的过程很简单.但是,有时完全控制 ...
- RHCE 系列(二):如何进行包过滤、网络地址转换和设置内核运行时参数
正如第一部分(“设置静态网络路由”)提到的,在这篇文章(RHCE 系列第二部分),我们首先介绍红帽企业版 Linux 7(RHEL)中包过滤和网络地址转换(NAT)的原理,然后再介绍在某些条件发生变化 ...
- mybaits入门
1.回顾jdbc开发 orm概述 orm是一种解决持久层对象关系映射的规则,而不是一种具体技术.jdbc/dbutils/springdao,hibernate/springorm,mybaits同属 ...
- SpringMVC进阶
1.springmvc(注解版本) 注解扫描 <?xml version="1.0" encoding="UTF-8"?> <beans xm ...
- Java - 简单的对象排序 - Comparator
注:对象排序,就是对对象中的某一字段进行比较,以正序或倒序进行排序. 例: 需要排序的对象: public class Person { public int age; public String n ...
- JSP相关
1.javax.servlet.jsp这个包两个接口,六个类 2.先说两个接口,分别是HttpJspPage,JspPage(JspPage是HttpJspPage的父类,JspPage 它自己继承至 ...
- 实现手机扫描二维码页面登录,类似web微信-第二篇,关于二维码的自动生成
转自:http://www.cnblogs.com/fengyun99/p/3541251.html 接上一章,我们已经基本把业务逻辑分析清楚了 下面我们第一步,实现二维码的web动态生成. 页面的二 ...
- 关于uboot和kernel的一些理解
经过多次的修改和实验,终于能够在mini2440开发板上进行各种uboot和kernel的挂载实验了,在此期间学习到了很多知识,也理解了一些知识1->分区uboot和kernel的分区表要一致u ...