風語·深蓝

Agile Methodology, HeadStorm And MindMap, they will change me.
posts - 55, comments - 306, trackbacks - 11, articles - 13

      以前在1.1.的时代我们为了写一个自定义配置,需要实现System.Configuration.IConfigurationSectionHandler接口,然后用System.Configuration.ConfigurationSettings.AppSettings.Get()方法去获取配置内容。在实现System.Configuration.IConfigurationSectionHandler的过程中会进行大量繁琐的XML节操作,如果希望Get()方法返回一个强类型的配置实体对象,还需要写一个相应的类。这些工作枯燥而且工作量很大,特别是在一个配置很复杂的时候。
      并且,1.1中的配置文件对于程序来说是只读的,若配置文件一旦发生改变怎会引发应用程序重启。

      而现在,2.0提供了全新的自定义配置文件构建方式,支持强类型的配置属性,并提供了代码对配置文件进行动态修改的机制。我对其作了一些初步的研究,在这里抛砖引玉了。


  1. 首先我们来看看最简单的情况如何处理:

    <?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();
            }


            
    所有配置属性
        }

    }



    上面的代码中可以看到核心代码是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"]
  2. 我们再来看看如何在代码中对配置节的内容进行修改:
    section.CompressLevel = Deflater.BEST_SPEED;
    config.Save();

    即在对配置对象的属性进行修改之后,用配置文件对象的save方法。你还可以用SaveAs方法存为别的文件。
  3. 这次就先讲那么多,下次再继续介绍更复杂的配置文件的处理方式,比如节点下有子节点的情况。如果你有什么发现也请告诉我。

Feedback

#1楼    回复  引用  查看    

2005-12-03 17:50 by 颓废边缘      
总算拜读到大作了~~ 呵呵 非常感谢带来这么好的.net2体验
收藏之

#2楼    回复  引用  查看    

2005-12-05 09:03 by sharp-edge      
拜读,我写1.1的,如果可以的话你也把2.0里对应结构的改变写出来,给大家做个对比,相信对很多人更好地掌握和理解还是很有用的,毕竟很多东西的演化过程才是最能指导人的

#3楼    回复  引用    

2005-12-06 17:18 by bryanzk [未注册用户]
怎么我这个版本的没有这个类啊? 

Microsoft Visual Studio 2005
Version 8.0.50727.42 (RTM.050727-4200)
Microsoft .NET Framework
Version 2.0.50727

Installed Edition: Enterprise

Microsoft Visual Basic 2005 77718-113-3000004-41229
Microsoft Visual Basic 2005

Microsoft Visual C# 2005 77718-113-3000004-41229
Microsoft Visual C# 2005

Microsoft Visual Studio Tools for Office 77718-113-3000004-41229
Microsoft Visual Studio Tools for the Microsoft Office System

Microsoft Visual Web Developer 2005 77718-113-3000004-41229
Microsoft Visual Web Developer 2005

Visual Studio 2005 Team Edition for Architects 77718-113-3000004-41229
Microsoft Visual Studio 2005 Team Edition for Software Architects

Visual Studio 2005 Team Edition for Developers 77718-113-3000004-41229
Microsoft Visual Studio 2005 Team Edition for Software Developers

Visual Studio 2005 Team Edition for Testers 77718-113-3000004-41229
Microsoft Visual Studio 2005 Team Edition for Software Testers

Crystal Reports AAC60-G0CSA4B-V7000AY
Crystal Reports for Visual Studio 2005

#4楼 [楼主]   回复  引用  查看    

2005-12-07 11:19 by 風語者·疾風      
需要添加引用System.Configuration.Dll

#5楼    回复  引用  查看    

2005-12-23 16:29 by 六子      
我在web site项目中,找不到程序集的名称?郁闷!!!大虾知道怎么取得程序集的名称吗?

#6楼    回复  引用    

2005-12-30 14:50 by bryanzk [未注册用户]
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
其中的OpenExeConfiguration方法的另外一个重载:
public static Configuration OpenExeConfiguration (
string exePath
)
,其中的exePath参数要求提供的是可执行文件的路径,比如我的项目属性为windows application,项目名称为CustomCfg,编译后的文件名为CustomCfg.exe,那么我的调用就是:

System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration("CustomCfg.exe");

#7楼    回复  引用    

2006-04-03 18:50 by LuXueQiang [未注册用户]
请教一下,如果有类似下面的树型结构,有没有好的方法吗?
<job name="all">
<job name="power" command="power on"/>
<job name="test tv">
<job name="step1.1" command="turn on tv" />
<job name="step1.2" command="turn off tv" />

#8楼 [楼主]   回复  引用  查看    

2006-04-04 08:50 by 風語者·疾風      
回LuXueQiang:
你说的这种我查到的方法似乎只能是
<add job name="all"/>
<add job name="power" command="power on"/>
<add job name="test tv">
<add name="step1.1" command="turn on tv" />
<add name="step1.2" command="turn off tv" />

直接像你那样写配置,如何识别,我确实没有发现。你若有发现也请告诉我。

#9楼    回复  引用    

2006-04-04 15:54 by LuXueQiang [未注册用户]
如果配置文件为:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
......
</configSections>
<XrinehartFramework>
<CommSupport>
<RemotingCompress AppName="A1" CompressLevel="DEFAULT_COMPRESSION" CompressCacheSize="1024" UnCompressCacheSize="1024" MinCompressSize="0">
<RemotingCompress AppName="A2" CompressLevel="DEFAULT_COMPRESSION" CompressCacheSize="1024" UnCompressCacheSize="1024" MinCompressSize="0">
</RemotingCompress>
</CommSupport>
</XrinehartFramework>
</configuration>

用以上方法是无法实现的.

#10楼 [楼主]   回复  引用  查看    

2006-04-04 16:24 by 風語者·疾風      
嗯,是的,我上面这个只写了最简单的。本来打算再写一篇深入的,涉及多条记录的配置,不过可惜一直都没腾出时间来写。
如果有兴趣告诉我你的信箱吧。我晚上给你发一段示例代码

#11楼    回复  引用    

2006-04-04 17:00 by LuXueQiang [未注册用户]
非常感谢!
我的信箱:LuXueQiang@tom.com

#12楼    回复  引用  查看    

2006-04-12 17:14 by hayatodragon      
请教一下
......
<Settings DefaultProvider="Access" >
<providers>
<add name="SQL" type="type" connectionString="string" databaseOwner="dbo" />
<add name="Access" type="type" connectionString="string">
</providers>
</Settings>
......
DefaultProvider我知道该如何读取了
但是像上面这种情况,有多个<add>节,而且其中的属性也也可能不同,该怎么处理啊?

#13楼    回复  引用  查看    

2006-04-12 17:15 by hayatodragon      
请教一下
......
<Settings DefaultProvider="Access" >
<providers>
<add name="SQL" type="type" connectionString="string" databaseOwner="dbo" />
<add name="Access" type="type" connectionString="string">
</providers>
</Settings>
......
DefaultProvider我知道该如何读取了
但是像上面这种情况,有多个<add>节,而且其中的属性也也可能不同,该怎么处理啊?

#14楼    回复  引用  查看    

2006-08-04 14:48 by 李.net      
我用最后的config.Save();保存修改后的数据
可是在应用程序中读取的时候是改的,但是在配置文件中数据还是没有变,这是怎么回事呢?>

#15楼    回复  引用  查看    

2006-08-26 02:45 by 上善若水      
这里提到的两个问题,
一:不能打开任意的配置文件
二:不能实现自定义的标记名称

我做了补充,可以到以下地址查看。
http://www.cnblogs.com/goldpicker/archive/2006/08/25/486675.html

#16楼    回复  引用    

2007-08-26 11:39 by 初学者 [未注册用户]
现在配置文件是这样的
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="Pics.My.MySettings.ConnectString" connectionString="Data Source=(local);Initial Catalog=jcjgl;Persist Security Info=True;User ID=webdb;Password=123456"
providerName="System.Data.SqlClient" />
</connectionStrings>
<userSettings>
<MySettings>
<setting name="InterFaceFile" serializeAs="String">
<value>default.ife</value>
</setting>
</MySettings>
</userSettings>
</configuration>

我想获得InterFaceFile节点的Value那该怎么写?




标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交