革新:.NET 2.0的自定义配置文件体系初探
2008-01-25 10:26
447 查看
http://www.cnblogs.com/Xrinehart/archive/2005/12/03/289978.html
以前在1.1.的时代我们为了写一个自定义配置,需要实现 System.Configuration.IConfigurationSectionHandler接口,然后用 System.Configuration.ConfigurationSettings.AppSettings.Get()方法去获取配置内容。在实 现System.Configuration.IConfigurationSectionHandler的过程中会进行大量繁琐的XML节操作,如果希 望Get()方法返回一个强类型的配置实体对象,还需要写一个相应的类。这些工作枯燥而且工作量很大,特别是在一个配置很复杂的时候。
并且,1.1中的配置文件对于程序来说是只读的,若配置文件一旦发生改变怎会引发应用程序重启。
而现在,2.0提供了全新的自定义配置文件构建方式,支持强类型的配置属性,并提供了代码对配置文件进行动态修改的机制。我对其作了一些初步的研究,在这里抛砖引玉了。
首先我们来看看最简单的情况如何处理:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="RemotingCompress" type="Xrinehart.Framework.CommSupport.Section.RemotingCompressSection, ConfigManagement"
allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/>
</configSections>
<RemotingCompress CompressLevel="DEFAULT_COMPRESSION" CompressCacheSize="1024" UnCompressCacheSize="1024" MinCompressSize="0">
</configuration>
只有一个配置节:RemotingCompress,拥有4个属性CompressLevel、CompressCacheSize、UnCompressCacheSize、MinCompressSize。
我们需要实现一个从System.Configuration.ConfigurationSection基类继承的配置类,在2.0里配置信息实体和配置识别都在一个类中,我们先来看代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace Xrinehart.Framework.CommSupport.Section
{
/**//// <summary>
/// 压缩率级别的枚举
/// </summary>
public enum Deflater
{
/**//// <summary>
/// 最佳压缩效果, 速度慢
/// </summary>
BEST_COMPRESSION = 9,
/**//// <summary>
/// 默认压缩率, 压缩速度比最高(推荐)
/// </summary>
DEFAULT_COMPRESSION = -1,
/**//// <summary>
/// 强化压缩率,速度较慢
/// </summary>
DEFLATED = 8,
/**//// <summary>
/// 最佳速度压缩率,速度最快(宽带推荐)
/// </summary>
BEST_SPEED = 1,
/**//// <summary>
/// 不压缩
/// </summary>
NO_COMPRESSION =0
};
/**//// <summary>
/// RemotingCompress配置节类
/// </summary>
public sealed class RemotingCompressSection : System.Configuration.ConfigurationSection
{
// 该配置文件只读
private static bool _ReadOnly = true;
public RemotingCompressSection()
{
}
private new bool IsReadOnly
{
get
{
return _ReadOnly;
}
}
private void ThrowIfReadOnly(string propertyName)
{
if (IsReadOnly)
throw new ConfigurationErrorsException(
"The property " + propertyName + " is read only.");
}
protected override object GetRuntimeObject()
{
// To enable property setting just assign true to
// the following flag.
_ReadOnly = true;
return base.GetRuntimeObject();
}
所有配置属性#region 所有配置属性
/**//// <summary>
/// 配置节属性:压缩率级别(可选)
/// </summary>
[ConfigurationProperty("CompressLevel", DefaultValue = "DEFAULT_COMPRESSION", Options = ConfigurationPropertyOptions.None)]
public Deflater CompressLevel
{
get
{
return (Deflater)this["CompressLevel"];
}
set
{
ThrowIfReadOnly("CompressLevel");
this["compressLevel"] = value;
}
}
/**//// <summary>
/// 配置节属性:压缩时缓冲区大小(可选)
/// </summary>
[ConfigurationProperty("CompressCacheSize", DefaultValue = (Int32)40960, Options = ConfigurationPropertyOptions.None)]
[IntegerValidator(MinValue = 1024, MaxValue = 1024 * 1024, ExcludeRange = false)]
public int CompressCacheSize
{
get
{
return (Int32)this["CompressCacheSize"];
}
set
{
ThrowIfReadOnly("CompressCacheSize");
this["CompressCacheSize"] = value;
}
}
/**//// <summary>
/// 配置节属性:解压时缓冲区大小(可选)
/// </summary>
[ConfigurationProperty("UnCompressCacheSize", DefaultValue = (Int32)40960, Options = ConfigurationPropertyOptions.None)]
[IntegerValidator(MinValue = 1024, MaxValue = 1024 * 1024, ExcludeRange = false)]
public int UnCompressCacheSize
{
get
{
return (Int32)this["UnCompressCacheSize"];
}
set
{
ThrowIfReadOnly("UnCompressCacheSize");
this["UnCompressCacheSize"] = value;
}
}
/**//// <summary>
/// 配置节属性:超过该值后的流才会被压缩(可选),暂未实现
/// </summary>
[ConfigurationProperty("MinCompressSize", DefaultValue = (Int32)40960, Options = ConfigurationPropertyOptions.None)]
[IntegerValidator(MinValue = 0, MaxValue = Int32.MaxValue, ExcludeRange = false)]
public int MinCompressSize
{
get
{
return (Int32)this["MinCompressSize"];
}
set
{
ThrowIfReadOnly("MinCompressSize");
this["MinCompressSize"] = value;
}
}
#endregion
}
}
上面的代码中可以看到核心代码是ConfigurationPropertyAttribute属性,在一个类属性上插入一个ConfigurationPropertyAttribute即可完成对配置文件中一个节点的属性的申明。
比如CompressLevel这个属性的定义:
/**//// <summary>
/// 配置节属性:压缩率级别(可选)
/// </summary>
[ConfigurationProperty("CompressLevel", DefaultValue = "DEFAULT_COMPRESSION", Options = ConfigurationPropertyOptions.None)]
public Deflater CompressLevel
{
get
{
return (Deflater)this["CompressLevel"];
}
set
{
ThrowIfReadOnly("CompressLevel");
this["compressLevel"] = value;
}
}
首 先,ConfigurationProperty的第一个参数"CompressLevel"这个是在XML配置文件中属性的名字,注意它是大小写敏感 的。而DefaultValue 则是设置该属性的默认值,Options设置有4种,分别是None, IsKey, IsRequired, IsDefaultCollection.这四项也可以单独在属性里分别设置。
若选择了None,则该属性可以在配置文件中不体现,而系统会去取 得设置的默认值(如果有设置的话); 若选择了IsRequired而在配置文件中没有体现,则会引发异常。另外,若所有一个配置节的所有属性都不 是必须的,在配置文件中即便没有这个配置节,依然可以在系统中得到该配置节的默认值信息。
请注意该属性是个枚举类型,而在属性中对类型进行转换,即可方便的实现,并不需要做其他更多的处理。
你也许注意到在代码中的一些属性有[IntegerValidator(MinValue = 0, MaxValue = Int32.MaxValue, ExcludeRange = false)]这 样的代码.是的,类库中提供了IntegerValidatorAttribute、LongValidatorAttribute、 RegexStringValidatorAttribute、StringValidatorAttribute、 TimeSpanValidatorAttribute默认的数据校验类,可以对XML中的该属性进行规范限制,并且你可以自己实现从 ConfigurationValidatorAttribute基类继承的自定义校验类,完成一些自己设定的校验,比如对上述的枚举类型值的限制。
接下来,我们看看如何访问到该配置节的。
首先在配置文件中添加识别节点的信息,参见上面。然后我们需要用到System.Configuration.ConfigurationManager.OpenMappedExeConfiguration()方法。
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
RemotingCompressSection section = config.Sections["RemotingCompress"] as RemotingCompressSection;
OpenMappedExeConfiguration()有两种重载,我只尝试成功了上述这种,另外一种说是可以从指定配置文件中得到配置对象,但我没成功过,谁要是搞明白了,记得告诉我下。
只需上面两行就可以做到,当然还可以更简单RemotingCompressSection section = ConfigurationManager.GetSection("RemotingCompress") as RemotingCompressSection。而我写上面这种写法是为了可以在运行时对配置文件内容进行修改。
另外,若配置文件有配置节点组,即
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="XrinehartFramework">
<sectionGroup name="CommSupport">
<section name="RemotingCompress" type="Xrinehart.Framework.CommSupport.Section.RemotingCompressSection, ConfigManagement"
allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/>
</sectionGroup>
</sectionGroup>
</configSections>
<XrinehartFramework>
<CommSupport>
<RemotingCompress CompressLevel="DEFAULT_COMPRESSION" CompressCacheSize="1024" UnCompressCacheSize="1024" MinCompressSize="0">
</RemotingCompress>
</CommSupport>
</XrinehartFramework>
</configuration>
你也只需要相应的改变下获取的代码,而不用去改变配置类
config.SectionGroups["XrinehartFramework"].SectionGroups["CommSupport"].Sections["RemotingCompress"]
我们再来看看如何在代码中对配置节的内容进行修改:
section.CompressLevel = Deflater.BEST_SPEED;
config.Save();
即在对配置对象的属性进行修改之后,用配置文件对象的save方法。你还可以用SaveAs方法存为别的文件。
这次就先讲那么多,下次再继续介绍更复杂的配置文件的处理方式,比如节点下有子节点的情况。如果你有什么发现也请告诉我。
以前在1.1.的时代我们为了写一个自定义配置,需要实现 System.Configuration.IConfigurationSectionHandler接口,然后用 System.Configuration.ConfigurationSettings.AppSettings.Get()方法去获取配置内容。在实 现System.Configuration.IConfigurationSectionHandler的过程中会进行大量繁琐的XML节操作,如果希 望Get()方法返回一个强类型的配置实体对象,还需要写一个相应的类。这些工作枯燥而且工作量很大,特别是在一个配置很复杂的时候。
并且,1.1中的配置文件对于程序来说是只读的,若配置文件一旦发生改变怎会引发应用程序重启。
而现在,2.0提供了全新的自定义配置文件构建方式,支持强类型的配置属性,并提供了代码对配置文件进行动态修改的机制。我对其作了一些初步的研究,在这里抛砖引玉了。
首先我们来看看最简单的情况如何处理:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="RemotingCompress" type="Xrinehart.Framework.CommSupport.Section.RemotingCompressSection, ConfigManagement"
allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/>
</configSections>
<RemotingCompress CompressLevel="DEFAULT_COMPRESSION" CompressCacheSize="1024" UnCompressCacheSize="1024" MinCompressSize="0">
</configuration>
只有一个配置节:RemotingCompress,拥有4个属性CompressLevel、CompressCacheSize、UnCompressCacheSize、MinCompressSize。
我们需要实现一个从System.Configuration.ConfigurationSection基类继承的配置类,在2.0里配置信息实体和配置识别都在一个类中,我们先来看代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace Xrinehart.Framework.CommSupport.Section
{
/**//// <summary>
/// 压缩率级别的枚举
/// </summary>
public enum Deflater
{
/**//// <summary>
/// 最佳压缩效果, 速度慢
/// </summary>
BEST_COMPRESSION = 9,
/**//// <summary>
/// 默认压缩率, 压缩速度比最高(推荐)
/// </summary>
DEFAULT_COMPRESSION = -1,
/**//// <summary>
/// 强化压缩率,速度较慢
/// </summary>
DEFLATED = 8,
/**//// <summary>
/// 最佳速度压缩率,速度最快(宽带推荐)
/// </summary>
BEST_SPEED = 1,
/**//// <summary>
/// 不压缩
/// </summary>
NO_COMPRESSION =0
};
/**//// <summary>
/// RemotingCompress配置节类
/// </summary>
public sealed class RemotingCompressSection : System.Configuration.ConfigurationSection
{
// 该配置文件只读
private static bool _ReadOnly = true;
public RemotingCompressSection()
{
}
private new bool IsReadOnly
{
get
{
return _ReadOnly;
}
}
private void ThrowIfReadOnly(string propertyName)
{
if (IsReadOnly)
throw new ConfigurationErrorsException(
"The property " + propertyName + " is read only.");
}
protected override object GetRuntimeObject()
{
// To enable property setting just assign true to
// the following flag.
_ReadOnly = true;
return base.GetRuntimeObject();
}
所有配置属性#region 所有配置属性
/**//// <summary>
/// 配置节属性:压缩率级别(可选)
/// </summary>
[ConfigurationProperty("CompressLevel", DefaultValue = "DEFAULT_COMPRESSION", Options = ConfigurationPropertyOptions.None)]
public Deflater CompressLevel
{
get
{
return (Deflater)this["CompressLevel"];
}
set
{
ThrowIfReadOnly("CompressLevel");
this["compressLevel"] = value;
}
}
/**//// <summary>
/// 配置节属性:压缩时缓冲区大小(可选)
/// </summary>
[ConfigurationProperty("CompressCacheSize", DefaultValue = (Int32)40960, Options = ConfigurationPropertyOptions.None)]
[IntegerValidator(MinValue = 1024, MaxValue = 1024 * 1024, ExcludeRange = false)]
public int CompressCacheSize
{
get
{
return (Int32)this["CompressCacheSize"];
}
set
{
ThrowIfReadOnly("CompressCacheSize");
this["CompressCacheSize"] = value;
}
}
/**//// <summary>
/// 配置节属性:解压时缓冲区大小(可选)
/// </summary>
[ConfigurationProperty("UnCompressCacheSize", DefaultValue = (Int32)40960, Options = ConfigurationPropertyOptions.None)]
[IntegerValidator(MinValue = 1024, MaxValue = 1024 * 1024, ExcludeRange = false)]
public int UnCompressCacheSize
{
get
{
return (Int32)this["UnCompressCacheSize"];
}
set
{
ThrowIfReadOnly("UnCompressCacheSize");
this["UnCompressCacheSize"] = value;
}
}
/**//// <summary>
/// 配置节属性:超过该值后的流才会被压缩(可选),暂未实现
/// </summary>
[ConfigurationProperty("MinCompressSize", DefaultValue = (Int32)40960, Options = ConfigurationPropertyOptions.None)]
[IntegerValidator(MinValue = 0, MaxValue = Int32.MaxValue, ExcludeRange = false)]
public int MinCompressSize
{
get
{
return (Int32)this["MinCompressSize"];
}
set
{
ThrowIfReadOnly("MinCompressSize");
this["MinCompressSize"] = value;
}
}
#endregion
}
}
上面的代码中可以看到核心代码是ConfigurationPropertyAttribute属性,在一个类属性上插入一个ConfigurationPropertyAttribute即可完成对配置文件中一个节点的属性的申明。
比如CompressLevel这个属性的定义:
/**//// <summary>
/// 配置节属性:压缩率级别(可选)
/// </summary>
[ConfigurationProperty("CompressLevel", DefaultValue = "DEFAULT_COMPRESSION", Options = ConfigurationPropertyOptions.None)]
public Deflater CompressLevel
{
get
{
return (Deflater)this["CompressLevel"];
}
set
{
ThrowIfReadOnly("CompressLevel");
this["compressLevel"] = value;
}
}
首 先,ConfigurationProperty的第一个参数"CompressLevel"这个是在XML配置文件中属性的名字,注意它是大小写敏感 的。而DefaultValue 则是设置该属性的默认值,Options设置有4种,分别是None, IsKey, IsRequired, IsDefaultCollection.这四项也可以单独在属性里分别设置。
若选择了None,则该属性可以在配置文件中不体现,而系统会去取 得设置的默认值(如果有设置的话); 若选择了IsRequired而在配置文件中没有体现,则会引发异常。另外,若所有一个配置节的所有属性都不 是必须的,在配置文件中即便没有这个配置节,依然可以在系统中得到该配置节的默认值信息。
请注意该属性是个枚举类型,而在属性中对类型进行转换,即可方便的实现,并不需要做其他更多的处理。
你也许注意到在代码中的一些属性有[IntegerValidator(MinValue = 0, MaxValue = Int32.MaxValue, ExcludeRange = false)]这 样的代码.是的,类库中提供了IntegerValidatorAttribute、LongValidatorAttribute、 RegexStringValidatorAttribute、StringValidatorAttribute、 TimeSpanValidatorAttribute默认的数据校验类,可以对XML中的该属性进行规范限制,并且你可以自己实现从 ConfigurationValidatorAttribute基类继承的自定义校验类,完成一些自己设定的校验,比如对上述的枚举类型值的限制。
接下来,我们看看如何访问到该配置节的。
首先在配置文件中添加识别节点的信息,参见上面。然后我们需要用到System.Configuration.ConfigurationManager.OpenMappedExeConfiguration()方法。
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
RemotingCompressSection section = config.Sections["RemotingCompress"] as RemotingCompressSection;
OpenMappedExeConfiguration()有两种重载,我只尝试成功了上述这种,另外一种说是可以从指定配置文件中得到配置对象,但我没成功过,谁要是搞明白了,记得告诉我下。
只需上面两行就可以做到,当然还可以更简单RemotingCompressSection section = ConfigurationManager.GetSection("RemotingCompress") as RemotingCompressSection。而我写上面这种写法是为了可以在运行时对配置文件内容进行修改。
另外,若配置文件有配置节点组,即
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="XrinehartFramework">
<sectionGroup name="CommSupport">
<section name="RemotingCompress" type="Xrinehart.Framework.CommSupport.Section.RemotingCompressSection, ConfigManagement"
allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/>
</sectionGroup>
</sectionGroup>
</configSections>
<XrinehartFramework>
<CommSupport>
<RemotingCompress CompressLevel="DEFAULT_COMPRESSION" CompressCacheSize="1024" UnCompressCacheSize="1024" MinCompressSize="0">
</RemotingCompress>
</CommSupport>
</XrinehartFramework>
</configuration>
你也只需要相应的改变下获取的代码,而不用去改变配置类
config.SectionGroups["XrinehartFramework"].SectionGroups["CommSupport"].Sections["RemotingCompress"]
我们再来看看如何在代码中对配置节的内容进行修改:
section.CompressLevel = Deflater.BEST_SPEED;
config.Save();
即在对配置对象的属性进行修改之后,用配置文件对象的save方法。你还可以用SaveAs方法存为别的文件。
这次就先讲那么多,下次再继续介绍更复杂的配置文件的处理方式,比如节点下有子节点的情况。如果你有什么发现也请告诉我。
相关文章推荐
- 革新:.NET 2.0的自定义配置文件体系初探
- 革新:.NET 2.0的自定义配置文件体系初探
- NET 2.0中WinForm自定义的程序配置文件Settings.setting使用方法
- [dotnetCore2.0]学习笔记之二: ASP.NET Core中,如何灵活使用静态文件和加载自定义配置
- ASP.NET 2.0加密Web.config 配置文件
- ASP.NET 2.0加密Web.config 配置文件
- ASP.NET 2.0加密Web.config 配置文件 (终极版)
- asp.net 2.0 读写配置文件
- ASP.NET 2.0加密网站配置文件中的信息
- Asp.net 2.0 操纵webconfig配置文件
- Quartz.NET 2.0 学习笔记(3) :通过配置文件实现任务调度
- ASP.NET 2.0 遍历配置文件的数据库连接字符串
- [导入]ASP.NET 2.0 遍历配置文件的数据库连接字符串
- NET 2.0 中的自定义配置处理
- Farseer.net轻量级开源框架 中级篇:自定义配置文件
- [导入]ASP.NET 2.0加密Web.config 配置文件
- ASP.NET 2.0加密Web.config 配置文件
- ASP.NET 2.0加密Web.config配置文件
- ASP.NET 2.0 遍历配置文件中的appSettings connectionStrings
- ASP.NET 2.0 读取配置文件[INI](示例代码下载)