之前介绍过Webconfig的具体知识ASP.NET基础知识汇总之WebConfig各节点介绍。今天准备封装一个ConfigHelper类,涉及到了自定义节点的东东,平时虽然一直用,但也没有系统的总结过,网上有很多关于自定义节点的精彩介绍。
一、为什么需要自定义节点?
大部分情况下,我们都是在<appsetting>中定义自己需要的参数,简单方便。如果配置的参数比较多,比较复杂的话就会显得杂乱无章,而且这种方式不支持复杂的层次节点也不支持强类型,所以有时候我们需要自定义节点。下面我们以配置redis参数和lognet参数为例,介绍自定义节点。
二、通过配置redis参数介绍自定义节点
先附上完整的配置信息如下
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="RedisConfig" type="MyRedisConfigurationHelper.MyRedisConfigurationSection,MyRedisConfigurationHelper" /> <section name="MyLog4net" type="MyLogConfigHelper.MyLog4netClass,MyLogConfigHelper"/> </configSections> <RedisConfig autoStart="true" dbIndex="0" password="redispass123" allowAdmin="true" abortConnect="false"> <ReadWriteHost> <add host="127.0.0.1:6379" /> </ReadWriteHost> <ReadOnlyHost> <add host="192.168.4.110:6379" /> </ReadOnlyHost> <MaxWritePoolSize size="65000" /> <MaxReadPoolSize size="65000" /> <SocketSendTimeout second="1000" /> <SocketReceiveTimeout second="1000" /> <ConnectTimeout second="1000" /> </RedisConfig> <MyLog4net> <add key="LogName" value="Test" /> <add key="LogLevel" value="4" /> </MyLog4net> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> </startup> <appSettings> <add key="CACHE_REDIS" value="true" /> </appSettings> <system.web> <membership defaultProvider="ClientAuthenticationMembershipProvider"> <providers> <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" connectionStringName="DefaultConnection" credentialsProvider="" /> </providers> </membership> <roleManager defaultProvider="ClientRoleProvider" enabled="true"> <providers> <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" connectionStringName="DefaultConnection" /> </providers> </roleManager> </system.web> <connectionStrings> <add name="DefaultConnection" connectionString="Data Source = |SQL/CE|" /> </connectionStrings> </configuration>
上边使用颜色标记的信息就是自定义的配置节点。自定义配置节点需要注意的事项如下:
1、自定义节点必须在configSections节点中。
2、section节点属性:name:必选的 String 属性,指定与 type 属性中指定的配置节处理程序关联的配置节或元素的名称。这是该元素在配置文件的节设置区域中使用的名称。type:必选的 String 属性,指定用来执行如下操作的配置节处理程序类的名称:处理在 name 属性中指定的节或元素中的配置设置。
3、section 元素将配置节处理程序与配置元素或节关联。每个 section 元素均标识一个配置节或元素。可以在 sectionGroup 元素中对 section 元素进行逻辑分组,以对 section 元素进行组织并避免命名冲突。section 和 sectionGroup 元素包含在 configSections 元素中。我们在这里没有介绍sectionGroup,毕竟在项目中自定义节点也不多,name不重复即可。
4、具体的一些特性和元素解释可以参考官网https://docs.microsoft.com/zh-cn/previous-versions/ms228245(v=vs.110)
5、
三、对自定义节点分块剖析
上边使用颜色标记的信息就是自定义的配置节点。蓝色标记的是Redis相关的自定义配置节点。绿色的是lognet相关的自定义配置信息。
1、log4net相关的自定义配置信息解析
<section name="MyLog4net" type="MyLog4netDemo.MyLog4netClass,MyLog4netDemo"/>
(1)其中name是配置文件中自定义节点设置区域使用的名称,就是标识设置具体自定义节点所使用的名称。比如:
<MyLog4net> <add key="LogName" value="Test" /> <add key="LogLevel" value="4" /> </MyLog4net>
(2)其中type中的MyLog4netClass就是自定义节点所需要的方法实现。针对于该自定义节点,实现方法如下:
using System; using System.Configuration; namespace MyLogConfigHelper { /// <summary> /// 读取自定义配置文件信息 /// </summary> public class MyLog4netClass : ConfigurationSection { private static readonly ConfigurationProperty property = new ConfigurationProperty(string.Empty, typeof(MyLog4netClassElementCollection), null, ConfigurationPropertyOptions.IsDefaultCollection); [ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)] public MyLog4netClassElementCollection KeyValues { get { return (MyLog4netClassElementCollection)base[property]; } } #region 读取自定义配置文件信息 private static MyLog4netClass _myLog4netClassProperty = null; public static MyLog4netClass MyLog4netClassProperty { get { return _myLog4netClassProperty; } set { _myLog4netClassProperty = value; } } static MyLog4netClass() { const string SETTINGS = "MyLog4net"; object section = null; if (System.Web.Hosting.HostingEnvironment.IsHosted) { //web.config section = ConfigurationManager.GetSection(SETTINGS); } else { //App.config section = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).Sections[SETTINGS]; } if (section is MyLog4netClass) { _myLog4netClassProperty = section as MyLog4netClass; } if (_myLog4netClassProperty == null) { throw new Exception("请在Config文件中配置<configSections> < section name =\"MyLog4net\" type=\"MyLog4netDemo.MyLog4netClass,MyLog4netDemo\"/></configSections>"); } } #endregion } /// <summary> /// 元素集合 /// </summary> [ConfigurationCollection(typeof(MyLog4netClassElement))] public class MyLog4netClassElementCollection : ConfigurationElementCollection { public MyLog4netClassElement this[int index] { get { return (MyLog4netClassElement)base.BaseGet(index); } set { if (base.BaseGet(index) != null) { base.BaseRemoveAt(index); } this.BaseAdd(index, value); } } /// <summary> /// 重写ConfigurationElementCollection中的方法 /// <summary> /// <returns></returns> protected override ConfigurationElement CreateNewElement() { return new MyLog4netClassElement(); } /// <summary> /// 重写ConfigurationElementCollection中的方法 /// </summary> /// <param name="element"></param> /// <returns></returns> protected override object GetElementKey(ConfigurationElement element) { return ((MyLog4netClassElement)element).Key; } } /// <summary> /// 集合中的每一个元素 实现MyLog4net集合中每一个元素的key value /// </summary> public class MyLog4netClassElement : ConfigurationElement { public MyLog4netClassElement() { } public MyLog4netClassElement(string key,string value) { this.Key = key; this.Value = value; } [ConfigurationProperty("key", IsRequired = true)] public string Key { get { return (string)base["key"]; } set { base["key"] = value; } } [ConfigurationProperty("value",IsRequired =true)] public string Value { get { return (string)base["value"]; } set { base["value"] = value; } } } }
函数入口:
using System; namespace MyLogConfigHelper { class Program { static void Main(string[] args) { MyLog4netClass myLog4netClass = MyLog4netClass.MyLog4netClassProperty; foreach (MyLog4netClassElement item in myLog4netClass.KeyValues) { Console.WriteLine("key:{0}", item.Key); Console.WriteLine("Value:{0}", item.Value); } Console.ReadKey(); } } }
2、RedisConfig相关的自定义节点剖析
(1)针对RedisConfig的实现代码如下:
using System; using System.Configuration; namespace MyRedisConfigurationHelper { #region Section 配置文件中 自定义RedisConfig节点的信息Model public class MyRedisConfigurationSection : ConfigurationSection { #region RedisConfig Model信息 [ConfigurationProperty("ReadOnlyHost", IsDefaultCollection = false)] [ConfigurationCollection(typeof(MyRedisConfigurationElement), CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap, RemoveItemName = "remove")] public MyRedisConfigurationElementCollection ReadOnlyHost { get { return (MyRedisConfigurationElementCollection)base["ReadOnlyHost"]; } } [ConfigurationProperty("ReadWriteHost", IsDefaultCollection = false)] [ConfigurationCollection(typeof(MyRedisConfigurationElement), CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap, RemoveItemName = "remove")] public MyRedisConfigurationElementCollection ReadWriteHost { get { return (MyRedisConfigurationElementCollection)base["ReadWriteHost"]; } } [ConfigurationProperty("MaxWritePoolSize", IsDefaultCollection = false)] public MaxWritePoolSizeConfigurationElement MaxWritePoolSize { get { return (MaxWritePoolSizeConfigurationElement)base["MaxWritePoolSize"]; } } [ConfigurationProperty("MaxReadPoolSize", IsDefaultCollection = false)] public MaxWritePoolSizeConfigurationElement MaxReadPoolSize { get { return (MaxWritePoolSizeConfigurationElement)base["MaxReadPoolSize"]; } } [ConfigurationProperty("SocketSendTimeout", IsDefaultCollection = false)] public SocketSendTimeoutConfigurationElement SocketSendTimeout { get { return (SocketSendTimeoutConfigurationElement)base["SocketSendTimeout"]; } } [ConfigurationProperty("SocketReceiveTimeout", IsDefaultCollection = false)] public SocketReceiveTimeoutConfigurationElement SocketReceiveTimeout { get { return (SocketReceiveTimeoutConfigurationElement)base["SocketReceiveTimeout"]; } } [ConfigurationProperty("ConnectTimeout", IsDefaultCollection = false)] public ConnectTimeoutConfigurationElement ConnectTimeout { get { return (ConnectTimeoutConfigurationElement)base["ConnectTimeout"]; } } [ConfigurationProperty("autoStart", IsDefaultCollection = false, DefaultValue = true)] public bool AutoStart { get { return (bool)base["autoStart"]; } } [ConfigurationProperty("abortConnect", IsDefaultCollection = false, DefaultValue = true)] public bool AbortConnect { get { return (bool)base["abortConnect"]; } } [ConfigurationProperty("dbIndex", IsDefaultCollection = false, DefaultValue = 0)] public int DbIndex { get { return (int)base["dbIndex"]; } } [ConfigurationProperty("password", IsDefaultCollection = false, DefaultValue = "")] public string Password { get { return (string)base["password"]; } } [ConfigurationProperty("allowAdmin", IsDefaultCollection = false, DefaultValue = false)] public bool AllowAdmin { get { return (bool)base["allowAdmin"]; } } #endregion #region 用来获取配置文件中的 自定义RedisConfig节点信息 private static MyRedisConfigurationSection _myRedisConfigurationSectionProperty = null; public static MyRedisConfigurationSection MyRedisConfigurationSectionProperty { get { return _myRedisConfigurationSectionProperty; } set { _myRedisConfigurationSectionProperty = value; } } static MyRedisConfigurationSection() { const string SETTINGS = "RedisConfig"; object section = null; if (System.Web.Hosting.HostingEnvironment.IsHosted) { //web.config section = ConfigurationManager.GetSection(SETTINGS); } else { //App.config section = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).Sections[SETTINGS]; } if (section is MyRedisConfigurationSection) { _myRedisConfigurationSectionProperty = section as MyRedisConfigurationSection; } if (_myRedisConfigurationSectionProperty == null) { throw new Exception("请在Config文件中配置<configSections> < section name =\"RedisConfig\" type=\"MyRedisConfigurationHelper.GetSectionClass,MyRedisConfigurationHelper\"/></configSections>"); } } #endregion } #endregion #region ElementCollection 用于接收 自定义RedisConfig多层元素节点 public class MyRedisConfigurationElementCollection: ConfigurationElementCollection { public MyRedisConfigurationElement this[int index] { get { return (MyRedisConfigurationElement)base.BaseGet(index); } set { if (base.BaseGet(index) != null) { base.BaseRemoveAt(index); } this.BaseAdd(index, value); } } protected override ConfigurationElement CreateNewElement() { return new MyRedisConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { return ((MyRedisConfigurationElement)element).Host; } } #endregion #region Element 集合中的每一个元素 声明RedisConfig集合中每一个元素 /// <summary> /// host ip地址 /// </summary> public class MyRedisConfigurationElement:ConfigurationElement { public MyRedisConfigurationElement() { } public MyRedisConfigurationElement(string host) { this.Host = host; } [ConfigurationProperty("host", IsRequired = true)] public string Host { get { return (string)base["host"]; } set { base["host"] = value; } } } /// <summary> /// Socket发送超时的配置信息 /// </summary> public class SocketSendTimeoutConfigurationElement : TimeoutConfigurationElement { } /// <summary> /// Socket接收超时的配置信息 /// </summary> public class SocketReceiveTimeoutConfigurationElement : TimeoutConfigurationElement { } /// <summary> /// Socket连接超时配置信息 /// </summary> public class ConnectTimeoutConfigurationElement : TimeoutConfigurationElement { } /// <summary> /// 写入连接池大小的配置信息 /// </summary> public class MaxWritePoolSizeConfigurationElement : SizeConfigurationElement { } /// <summary> /// 连接池大小的配置信息 /// </summary> public abstract class SizeConfigurationElement : ConfigurationElement { [ConfigurationProperty("size", IsRequired = true, IsKey = true, DefaultValue = 60)] public int Size { get { return (int)base["size"]; } set { base["size"] = value; } } } /// <summary> /// Socket超时的配置信息 /// </summary> public abstract class TimeoutConfigurationElement : ConfigurationElement { [ConfigurationProperty("second", IsRequired = true, IsKey = true, DefaultValue = 1000)] public int Second { get { return (int)base["second"]; } set { base["second"] = value; } } } #endregion }
(2)函数入口:
using System; namespace MyRedisConfigurationHelper { class Program { static void Main(string[] args) { MyRedisConfigurationSection myRedisConfig = MyRedisConfigurationSection.MyRedisConfigurationSectionProperty; Console.WriteLine(myRedisConfig.ReadOnlyHost); Console.ReadKey(); } } }
四、代码下载
其实就是对Element、ElementCollection、Section的操作