目前项目里的配置文件用的还是以前的那种Segment形式的配置文件,结构比较混乱,管理和维护也很困难。我希望按照.NET的现有模式重新开发一个配置的保存方式和读写接口。为此,我查询了一些MSDN资料,不过依然还是有很多不明白的地方。还请大牛们指点一二。1、根据MSDN的说明,创建自定义配置节一般使用ConfigurationSection。我根据相关的例子自己写了一个很简单的测试:public partial class FrmConfiguration : Form
    {
        public FrmConfiguration()
        {
            InitializeComponent();            //object obj = System.Configuration.ConfigurationManager.GetSection("MyConfig");
            MyConfig myConfig = System.Configuration.ConfigurationManager.GetSection("MyConfig") as MyConfig;
            label1.Text = myConfig.PSAEnabled;
        }
    }    public class MyConfig : ConfigurationSection
    {
        [ConfigurationProperty("PSAEnabled", DefaultValue = "true")]
        public string PSAEnabled
        {
            get { return (string)this["PSAEnalbed"]; }
            set { this["PSAEnalbed"] = value; }
        }
    }
除了写一个MyConfig类,我没有做任何其它工作,例如给项目添加一个配置文件。测试结果是GetSection返回null,这表明我还有一些工作没做,请问我还要做些什么才能让这上程序跑起来?2、GetSection函数没有参数用于指定配置文件,根据MSDN说明,此方法检索通过合并应用程序配置文件、本地用户配置文件和漫游配置文件而获得的最终配置文件。那么,GetSection函数将根据什么规则来查找配置文件?3、MSDN中描述了另一种ConfigurationSection的派生方式,这种方式使用静态成员,如下:public sealed class CustomSection : ConfigurationSection
    {
        // The collection (property bag) that conatains 
        // the section properties.
        private static ConfigurationPropertyCollection _Properties;        // Internal flag to disable 
        // property setting.
        private static bool _ReadOnly;        // The FileName property.
        private static readonly ConfigurationProperty _FileName = new ConfigurationProperty("fileName", typeof(string), "default.txt", ConfigurationPropertyOptions.IsRequired);        // The MasUsers property.
        private static readonly ConfigurationProperty _MaxUsers = new ConfigurationProperty("maxUsers", typeof(long), (long)1000, ConfigurationPropertyOptions.None);        // The MaxIdleTime property.
        private static readonly ConfigurationProperty _MaxIdleTime = new ConfigurationProperty("maxIdleTime", typeof(TimeSpan), TimeSpan.FromMinutes(5), ConfigurationPropertyOptions.IsRequired);        // CustomSection constructor.
        public CustomSection()
        {
            // Property initialization
            _Properties = new ConfigurationPropertyCollection();            _Properties.Add(_FileName);
            _Properties.Add(_MaxUsers);
            _Properties.Add(_MaxIdleTime);
        }        // This is a key customization. 
        // It returns the initialized property bag.
        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                return _Properties;
            }
        }        private new bool IsReadOnly
        {
            get
            {
                return _ReadOnly;
            }
        }        // Use this to disable property setting.
        private void ThrowIfReadOnly(string propertyName)
        {
            if (IsReadOnly)
                throw new ConfigurationErrorsException(
                    "The property " + propertyName + " is read only.");
        }
        // Customizes the use of CustomSection
        // by setting _ReadOnly to false.
        // Remember you must use it along with ThrowIfReadOnly.
        protected override object GetRuntimeObject()
        {
            // To enable property setting just assign true to
            // the following flag.
            _ReadOnly = true;
            return base.GetRuntimeObject();
        }
        [StringValidator(InvalidCharacters = " ~!@#$%^&*()[]{}/;'\"|\\",
            MinLength = 1, MaxLength = 60)]
        public string FileName
        {
            get
            {
                return (string)this["fileName"];
            }
            set
            {
                // With this you disable the setting.
                // Renemmber that the _ReadOnly flag must
                // be set to true in the GetRuntimeObject.
                ThrowIfReadOnly("FileName");
                this["fileName"] = value;
            }
        }        [LongValidator(MinValue = 1, MaxValue = 1000000,
            ExcludeRange = false)]
        public long MaxUsers
        {
            get
            {
                return (long)this["maxUsers"];
            }
            set
            {
                this["maxUsers"] = value;
            }
        }        [TimeSpanValidator(MinValueString = "0:0:30",
            MaxValueString = "5:00:0",
            ExcludeRange = false)]
        public TimeSpan MaxIdleTime
        {
            get
            {
                return (TimeSpan)this["maxIdleTime"];
            }
            set
            {
                this["maxIdleTime"] = value;
            }
        }
    }这两种方式有何区别?后者如何使用?4、请推荐一些与此相关的书籍或源代码。谢谢!

解决方案 »

  1.   

    感觉区别在于sealed 是否能被继承。第一种,进行一下追加保存就可以了。 MyConfig configData = new MyConfig();
     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
     config.Sections.Remove("MyConfig");
     config.Sections.Add("MyConfig", configData);
     config.Save();
      

  2.   

    非常感谢,问题已几近解决,还有一个小问题,我的项目里有一个配置文件ConfigTest.config:
    Configuration MyConfig = ConfigurationManager.OpenExeConfiguration("ConfigTest.config");
    //modify ...
    MyConfig.Save(Full);发现程序居然创建并把更改后的数据保存到了一个新文件ConfigTest.config.config。
    在我把打开的代码改为:
    Configuration MyConfig = ConfigurationManager.OpenExeConfiguration("ConfigTest");
    后,程序又提示找不到路径。为什么会出现这种打开要全部文件名,而保存时认为是不带后缀文件名的状况呢?