Reading and writing values in.NET .config files

两盒软妹~` 提交于 2020-01-23 13:11:09

问题


I want to use a custom path for a user.config file, rather than have .NET read it from the default location.

I am opening the file like this:

ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = String.Format("{0}\\user.config",AppDataPath);
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.PerUserRoamingAndLocal);

But I can't figure out how to actually read settings out of it, I get a compile error saying that the values are inaccessible when I try to get a value through AppData or ConfigurationSection.

Do I need to create some sort of a wrapper class to consume the data properly?


回答1:


I was recently tasked with a similar problem, I had to change the location of where settings files were read from the default location in AppData to the Application directory. My solution was to create my own settings files that derived from ApplicationSettingsBase which specified a custom SettingsProvider. While the solution felt like overkill at first, I've found it to be more flexible and maintainable than I had anticipated.

Update:

Sample Settings File:

public class BaseSettings : ApplicationSettingsBase
{
    protected BaseSettings(string settingsKey)
       { SettingsKey = settingsKey.ToLower(); }


    public override void Upgrade()
    {
         if (!UpgradeRequired)
             return;
         base.Upgrade();
         UpgradeRequired = false;
         Save();
    }


    [SettingsProvider(typeof(MySettingsProvider)), UserScopedSetting]
    [DefaultSettingValue("True")]
    public bool UpgradeRequired
    {
         get { return (bool)this["UpgradeRequired"]; }
         set { this["UpgradeRequired"] = value; }
    }
}

Sample SettingsProvider:

public sealed class MySettingsProvider : SettingsProvider
{
    public override string ApplicationName { get { return Application.ProductName; } set { } }
    public override string Name { get { return "MySettingsProvider"; } }


    public override void Initialize(string name, NameValueCollection col)
         { base.Initialize(ApplicationName, col); }


    public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propertyValues)
    {
       // Use an XmlWriter to write settings to file. Iterate PropertyValueCollection and use the SerializedValue member
    }


    public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props)
    {
       // Read values from settings file into a PropertyValuesCollection and return it
    }


    static MySettingsProvider()
    {
        appSettingsPath_ = Path.Combine(new FileInfo(Application.ExecutablePath).DirectoryName, settingsFileName_);

        settingsXml_ = new XmlDocument();
        try { settingsXml_.Load(appSettingsPath_); }
        catch (XmlException) { CreateXmlFile_(settingsXml_); } //Invalid settings file
        catch (FileNotFoundException) { CreateXmlFile_(settingsXml_); } // Missing settings file
    }
}



回答2:


A few improvements:

1) Load it up a bit simpler, no need for the other lines:

var config = ConfigurationManager.OpenExeConfiguration(...);

2) Access AppSettings properly:

config.AppSettings.Settings[...]; // and other things under AppSettings

3) If you want a custom configuration section, use this tool: http://csd.codeplex.com/




回答3:


I never ended up getting the Configuration Manager approach working. After spending a half day muddling with no progress, I decided to roll my own solution as my needs are basic.

Here is the solution I came up with in the end:

public class Settings
{
    private XmlDocument _xmlDoc;
    private XmlNode _settingsNode;
    private string _path;

    public Settings(string path)
    {
        _path = path;
        LoadConfig(path);
    }

    private void LoadConfig(string path)
    {
       //TODO: add error handling
        _xmlDoc = null;
        _xmlDoc = new XmlDocument();
        _xmlDoc.Load(path);
        _settingsNode = _xmlDoc.SelectSingleNode("//appSettings");
    }

    //
    //use the same structure as in .config appSettings sections
    //
    public string this[string s]
    {
        get
        {
            XmlNode n = _settingsNode.SelectSingleNode(String.Format("//add[@key='{0}']", s));
            return n != null ? n.Attributes["value"].Value : null;
        }
        set
        {
            XmlNode n = _settingsNode.SelectSingleNode(String.Format("//add[@key='{0}']", s));

            //create the node if it doesn't exist
            if (n == null)
            {
                n=_xmlDoc.CreateElement("add");
                _settingsNode.AppendChild(n);
                XmlAttribute attr =_xmlDoc.CreateAttribute("key");
                attr.Value = s;
                n.Attributes.Append(attr);
                attr = _xmlDoc.CreateAttribute("value");
                n.Attributes.Append(attr);
            }

            n.Attributes["value"].Value = value;
            _xmlDoc.Save(_path);
        }
    }
}


来源:https://stackoverflow.com/questions/10466098/reading-and-writing-values-in-net-config-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!