在user.config的自定义路径 [英] Custom path of the user.config

查看:141
本文介绍了在user.config的自定义路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用VS2008中的设置设计师管理我的应用程序设置。


  

的user.config的确切路径
  文件看起来是这样的:


 <配置文件目录> \\<公司名称> \\
 <应用程序名称> _<证据类型> _<证据哈希> \\<版本> \\ user.config

有没有一种方法来定制这条道路?我想preFER是这样的:

 <配置文件目录> \\<公司名称> \\
 <应用程序名称> \\<版本> \\ user.config

我注意到,白色的空间都在公司名称下划线在新创建的文件夹(测试公司 - >Test_Company)取代。我真的希望关掉此行为。

您知道吗,我可以写一个新的基于XML的设置处理程序,但我想使用的设置设计师。


解决方案

这是不容易找到在实现自定义的设置提供,所以我下面包括完整实现良好的信息(底部)的格式user.config文件被保留,以及.settings设计师内的功能。我敢肯定有可以清理一个龙套,所以不要我费尽口舌:)

与其他人一样,我想改变user.config文件的位置,仍然可以得到与.settings文件工作的设计师,其中包括新安装创建的默认值的乐趣和花哨。重要的是,我们的应用程序也已经有其他保存设置的对象出现在路径(应用程序数据\\本地\\等)中,我们已经决定,我们并不想在多个地点的文物。

在code是远远长于我希望它是,但没有简单的答案,我能找到。虽然它似乎有点痛苦只是为了能够控制的路径,创建自定义设置提供本身仍然是pretty强大。人们可以改变follwing执行存储数据的几乎任何地方,包括一个自定义的加密文件,数据库或与Web serivice交互。

从我读过,微软并不打算使路径配置文件配置。我会带他们的话时,他们说让那将是可怕的。见(<一个href=\"http://connect.microsoft.com/VisualStudio/feedback/details/93540/cannot-set-path-for-user-config-when-using-applicationsettingsbase\">this)帖子。唉,如果你想自己做,你必须实现自己的<一个href=\"http://msdn.microsoft.com/en-us/library/system.configuration.settingsprovider.aspx\">SettingsProvider.

下面去..

在您的项目添加引用 System.Configuration 的,你需要它来实现SettingsProvider。

轻松位 ...创建一个实现SettingsProvider类,使用 CTRL + 。来帮助你。

 类CustomSettingsProvider:SettingsProvider

另一个简单的位 ...转到您的.settings文件背后的code(有在设计一个按钮)和装饰类它指向您的实现。这一操作必须完成覆盖内置的功能,但它不会改变设计师是如何工作的。(抱歉格式这里是怪异的)

[System.Configuration.SettingsProvider(typeof(YourCompany.YourProduct.CustomSettingsProvider))]

 公共密封部分类设置
{
    //唧唧歪歪
}

获取路径:有一个叫我用这个存储路径SettingsKey(例如Properties.Settings.Default.SettingsKey)属性。我做了以下属性。

  ///&LT;总结&gt;
///此函数返回用于设置之前必须设置的关键。
例如/// &LT; c基Properties.Settings.Default.SettingsKey = @C:\\ TEMP \\ user.config;&LT; / c取代;
///&LT; /总结&gt;
私人字符串UserConfigPath
{
    得到
    {
        返回Properties.Settings.Default.SettingsKey;
    }}

存储设置值。我选择使用一本字典。这将让在一个位广泛使用。我创建了一个结构类型作为帮手。

  ///&LT;总结&gt;
///在设置值的存储器
///&LT; /总结&gt;
私人字典&LT;字符串,SettingStruct&GT; SettingsDictionary {搞定;组; }///&LT;总结&gt;
///助手结构。
///&LT; /总结&gt;
内部结构SettingStruct
{
    内部字符串名称;
    内部字符串serializeAs;
    内部字符串值;
}

神奇。您必须覆盖2种方法, GetPropertyValues​​ SetPropertyValues​​ 。 GetPropertyValues​​临危因为你在设计看到一个参数,你要的机会更新值,并返回一个新的集合的。当用户保存在运行时所做的值进行任何更改SetPropertyValues​​被称为,这是我的更新字典和写出来的文件的。

  ///&LT;总结&gt;
///必须重写此,这是设计师的属性相匹配的字典中的值的位
///&LT; /总结&gt;
///&LT; PARAM NAME =上下文&GT;&LT; /参数&GT;
///&LT; PARAM NAME =集合&GT;&LT; /参数&GT;
///&LT;&回报GT;&LT; /回报&GT;
公众覆盖SettingsPropertyValueCollection GetPropertyValues​​(SettingsContext背景下,SettingsPropertyCollection集合)
{
    //加载文件
    如果(!_loaded)
    {
         _loaded = TRUE;
         LoadValues​​FromFile();
    }    //集合,将被退回。
    SettingsPropertyValueCollection值=新SettingsPropertyValueCollection();    //迭代认为我们从设计者得到的属性,检查是否设置为在字典
    的foreach(在收集SettingsProperty设置)
    {
        SettingsPropertyValue值=新SettingsPropertyValue(设置);
        value.IsDirty = FALSE;        //需要值的类型为强类型
        VAR T = Type.GetType(setting.PropertyType.FullName);        如果(SettingsDictionary.ContainsKey(setting.Name))
        {
            value.SerializedValue = SettingsDictionary [setting.Name] .value的;
            value.PropertyValue = Convert.ChangeType(SettingsDictionary [setting.Name] .value的,T);
        }
        否则//的情况下使用默认设置在没有设置还
        {
            value.SerializedValue = setting.DefaultValue;
            value.PropertyValue = Convert.ChangeType(setting.DefaultValue,T);
        }            values​​.Add(值);
    }
    返回值;
}///&LT;总结&gt;
///必须重写此,这是不保存到文件的位。调用时Settings.Save()被调用
///&LT; /总结&gt;
///&LT; PARAM NAME =上下文&GT;&LT; /参数&GT;
///&LT; PARAM NAME =集合&GT;&LT; /参数&GT;
公共覆盖无效SetPropertyValues​​(SettingsContext背景下,SettingsPropertyValueCollection集合)
{
    //取得从集合参数值,并在我们的字典更新值。
    的foreach(在收集SettingsPropertyValue值)
    {
        VAR值=新SettingStruct()
        {
            值=(?value.PropertyValue == NULL的String.Empty:value.PropertyValue.ToString()),
            名称= value.Name,
            serializeAs = value.Property.SerializeAs.ToString()
        };        如果(!SettingsDictionary.ContainsKey(value.Name))
        {
            SettingsDictionary.Add(value.Name,设置);
        }
        其他
        {
            SettingsDictionary [value.Name] =设置;
        }
    }    //现在,我们的本地字典是最新的最新的,它保存到磁盘。
    SaveValues​​ToFile();
}

的完整解决方案。因此,这里的整个类,其中包括构造函数,初始化和辅助方法。随意剪切/粘贴切片和切块。

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Configuration;
使用的System.Reflection;
使用System.Xml.Linq的;
使用System.IO;命名空间YourCompany.YourProduct
{
    类CustomSettingsProvider:SettingsProvider
    {
        常量字符串NAME =名;
        常量字符串SERIALIZE_AS =serializeAs;
        常量字符串CONFIG =配置;
        常量字符串USER_SETTINGS =userSettings;
        常量字符串设定=设置;        ///&LT;总结&gt;
        ///加载文件到内存中。
        ///&LT; /总结&gt;
        公共CustomSettingsProvider()
        {
            SettingsDictionary =新词典&LT;字符串,SettingStruct&GT;();        }        ///&LT;总结&gt;
        ///覆盖。
        ///&LT; /总结&gt;
        公共覆盖无效初始化(字符串名称,System.Collections.Specialized.NameValueCollection配置)
        {
            base.Initialize(应用程序名称,配置);
        }        ///&LT;总结&gt;
        ///覆盖。
        ///&LT; /总结&gt;
        公众覆盖字符串的应用程序名称
        {
            得到
            {
                返回System.Reflection.Assembly.GetExecutingAssembly()ManifestModule.Name。
            }
            组
            {
                //没做什么
            }
        }        ///&LT;总结&gt;
        ///必须重写此,这是设计师的属性相匹配的字典中的值的位
        ///&LT; /总结&gt;
        ///&LT; PARAM NAME =上下文&GT;&LT; /参数&GT;
        ///&LT; PARAM NAME =集合&GT;&LT; /参数&GT;
        ///&LT;&回报GT;&LT; /回报&GT;
        公众覆盖SettingsPropertyValueCollection GetPropertyValues​​(SettingsContext背景下,SettingsPropertyCollection集合)
        {
            //加载文件
            如果(!_loaded)
            {
                _loaded = TRUE;
                LoadValues​​FromFile();
            }            //集合,将被退回。
            SettingsPropertyValueCollection值=新SettingsPropertyValueCollection();            // itterate认为我们从设计者得到的属性,检查是否设置为在字典
            的foreach(在收集SettingsProperty设置)
            {
                SettingsPropertyValue值=新SettingsPropertyValue(设置);
                value.IsDirty = FALSE;                //需要值的类型为强类型
                VAR T = Type.GetType(setting.PropertyType.FullName);                如果(SettingsDictionary.ContainsKey(setting.Name))
                {
                    value.SerializedValue = SettingsDictionary [setting.Name] .value的;
                    value.PropertyValue = Convert.ChangeType(SettingsDictionary [setting.Name] .value的,T);
                }
                否则//的情况下使用默认设置在没有设置还
                {
                    value.SerializedValue = setting.DefaultValue;
                    value.PropertyValue = Convert.ChangeType(setting.DefaultValue,T);
                }                values​​.Add(值);
            }
            返回值;
        }        ///&LT;总结&gt;
        ///必须重写此,这是不保存到文件的位。调用时Settings.Save()被调用
        ///&LT; /总结&gt;
        ///&LT; PARAM NAME =上下文&GT;&LT; /参数&GT;
        ///&LT; PARAM NAME =集合&GT;&LT; /参数&GT;
        公共覆盖无效SetPropertyValues​​(SettingsContext背景下,SettingsPropertyValueCollection集合)
        {
            //取得从集合参数值,并在我们的字典更新值。
            的foreach(在收集SettingsPropertyValue值)
            {
                VAR值=新SettingStruct()
                {
                    值=(?value.PropertyValue == NULL的String.Empty:value.PropertyValue.ToString()),
                    名称= value.Name,
                    serializeAs = value.Property.SerializeAs.ToString()
                };                如果(!SettingsDictionary.ContainsKey(value.Name))
                {
                    SettingsDictionary.Add(value.Name,设置);
                }
                其他
                {
                    SettingsDictionary [value.Name] =设置;
                }
            }            //现在,我们的本地字典是最新的最新的,它保存到磁盘。
            SaveValues​​ToFile();
        }        ///&LT;总结&gt;
        ///加载该文件的值到存储器中。
        ///&LT; /总结&gt;
        私人无效LoadValues​​FromFile()
        {
            如果(!File.Exists(UserConfigPath))
            {
                //如果配置文件是不是它应该是创建一个新的。
                CreateEmptyConfig();
            }            //加载XML
            VAR configXml = XDocument.Load(UserConfigPath);            //获取所有的&lt的;设置名称=...serializeAs =...&GT;元素。
            VAR settingElements = configXml.Element(CONFIG).Element(USER_SETTINGS).Element(typeof(Properties.Settings).FullName).Elements(SETTING);            //遍历,将它们添加到字典中,(检查空值,XML没有LIKEY归零)
            //使用字符串作为默认serializeAs ......为了以防万一,没有真正的很好的理由。
            的foreach(在settingElements VAR元素)
            {
                VAR newSetting =新SettingStruct()
                {
                    名称= element.Attribute(NAME)== NULL?的String.Empty:element.Attribute(NAME).value的,
                    serializeAs = element.Attribute(SERIALIZE_AS)== NULL? 字符串:element.Attribute(SERIALIZE_AS).value的,
                    值= element.Value?的String.Empty
                };
                SettingsDictionary.Add(element.Attribute(NAME).value的,newSetting);
            }
        }        ///&LT;总结&gt;
        ///创建一个空文件user.config ...看起来像一个MS造成的。
        ///这可能是矫枉过正,一个简单的键/值对可能会做。
        ///&LT; /总结&gt;
        私人无效CreateEmptyConfig()
        {
            VAR DOC =新的XDocument();
            变种声明=新XDeclaration(1.0,UTF-8,真);
            无功配置=新的XElement(CONFIG);
            VAR userSettings =新的XElement(USER_SETTINGS);
            VAR组=新的XElement(typeof运算(Properties.Settings).FullName);
            userSettings.Add(组);
            config.Add(userSettings);
            doc.Add(配置);
            doc.Declaration =声明;
            doc.Save(UserConfigPath);
        }        ///&LT;总结&gt;
        ///保存在内存中的字典给用户配置文件
        ///&LT; /总结&gt;
        私人无效SaveValues​​ToFile()
        {
            //加载该文件中的当前XML。
            VAR进口= XDocument.Load(UserConfigPath);            //获取设置组(例如小于Company.Project.Desktop.Settings&GT;)
            VAR settingsSection = import.Element(CONFIG).Element(USER_SETTINGS).Element(typeof运算(Properties.Settings).FullName);            //迭代虽然字典,或者更新值或添加新的设置。
            的foreach(在SettingsDictionary VAR进入)
            {
                VAR值= settingsSection.Elements()FirstOrDefault(E =&GT; e.Attribute(NAME).value的== entry.Key)。
                如果(设置== NULL)//如果新的设置是通过.settings设计师加入会发生这种情况。
                {
                    VAR newSetting =新的XElement(设置);
                    newSetting.Add(新XAttribute(NAME,entry.Value.name));
                    newSetting.Add(新XAttribute(SERIALIZE_AS,entry.Value.serializeAs));
                    newSetting.Value =(entry.Value.value ??的S​​tring.Empty);
                    settingsSection.Add(newSetting);
                }
                如果存在其他//更新值。
                {
                    setting.Value =(entry.Value.value ??的S​​tring.Empty);
                }
            }
            import.Save(UserConfigPath);
        }        ///&LT;总结&gt;
        ///此函数返回用于设置之前必须设置的设置键。
        例如/// &LT; c基Properties.Settings.Default.SettingsKey = @C:\\ TEMP \\ user.config;&LT; / c取代;
        ///&LT; /总结&gt;
        私人字符串UserConfigPath
        {
            得到
            {
                返回Properties.Settings.Default.SettingsKey;
            }        }        ///&LT;总结&gt;
        ///在设置值的存储器
        ///&LT; /总结&gt;
        私人字典&LT;字符串,SettingStruct&GT; SettingsDictionary {搞定;组; }        ///&LT;总结&gt;
        ///助手结构。
        ///&LT; /总结&gt;
        内部结构SettingStruct
        {
            内部字符串名称;
            内部字符串serializeAs;
            内部字符串值;
        }        布尔_loaded;
    }
}

I manage my application-settings using the setting-designer in VS2008.

"The exact path of the user.config files looks something like this:"

<Profile Directory>\<Company Name>\
 <App Name>_<Evidence Type>_<Evidence Hash>\<Version>\user.config

Is there to a way to customize this path? I would prefer something like this:

<Profile Directory>\<Company Name>\
 <App Name>\<Version>\user.config

I noticed that white-spaces were replaced by underscores in the "Company Name" in the new created folder ("Test Company" --> "Test_Company"). I really wish to turn off this behavior.

You know, I could write a new XML-based setting-handler, but I would like to use the setting-designer.

解决方案

It hasn't been easy to find good info on implementing a custom settings provider so I'm including a complete implementation below (bottom.) The format of the user.config file is retained, as well as the functionality within the .settings designer. I'm certain there are parts that can be cleaned up a bit, so don't hassle me :)

Like others, I wanted to change the location of the user.config file and still get the fun and fanciness of working with the .settings files in the designer, including creating default values for new installations. Importantly, our app also already has other saved settings objects at a path (appData\local\etc) in which we have already decided, and we didn't want artifacts in multiple locations.

The code is much longer than I'd like it to be, but there is no SHORT answer that I could find. Though it seems somewhat painful just to be able to control the path, creating a custom settings provider in itself is still pretty powerful. One could alter the follwing implementation to store the data just about anywhere including a custom encrypted file, database, or interact with a web serivice.

From what I've read, Microsoft does not intend on making the path to the config file configurable. I'll take their word for it when they say allowing that would be scary. See (this) post. Alas, if you want to do it yourself you must implement your own SettingsProvider.

Here goes..

Add a reference in your project to System.Configuration, you'll need it to implement the SettingsProvider.

Easy bit...Create a class which implements SettingsProvider, use ctrl+. to help you out.

class CustomSettingsProvider : SettingsProvider

Another easy bit...Go to the code behind of your .settings file (there is a button in the designer) and decorate the class to point it to your implementation. This must be done to override the built in functionality, but it does not change how the designer works.(sorry the formatting here is weird)

[System.Configuration.SettingsProvider(typeof(YourCompany.YourProduct.CustomSettingsProvider))]

public sealed partial class Settings
{
    //bla bla bla
}

Getting the path: There is a property called "SettingsKey" (e.g. Properties.Settings.Default.SettingsKey) I used this to store the path. I made the following property.

/// <summary>
/// The key this is returning must set before the settings are used.
/// e.g. <c>Properties.Settings.Default.SettingsKey = @"C:\temp\user.config";</c>
/// </summary>
private string UserConfigPath
{
    get
    {
        return Properties.Settings.Default.SettingsKey;
    }

}

Storing the settings values. I chose to use a dictionary. This will get used extensively in a bit. I created a struct as a helper.

/// <summary>
/// In memory storage of the settings values
/// </summary>
private Dictionary<string, SettingStruct> SettingsDictionary { get; set; }

/// <summary>
/// Helper struct.
/// </summary>
internal struct SettingStruct
{
    internal string name;
    internal string serializeAs;
    internal string value;
}

The magic. You must override 2 methods, GetPropertyValues and SetPropertyValues. GetPropertyValues recieves as a parameter what you see in the designer, you have to opportunity to update the values and return a new collection. SetPropertyValues is called when the user saves any changes to the values made at runtime, this is where I update the dictionary and write out the file.

/// <summary>
/// Must override this, this is the bit that matches up the designer properties to the dictionary values
/// </summary>
/// <param name="context"></param>
/// <param name="collection"></param>
/// <returns></returns>
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
{
    //load the file
    if (!_loaded)
    {
         _loaded = true;
         LoadValuesFromFile();
    }

    //collection that will be returned.
    SettingsPropertyValueCollection values = new SettingsPropertyValueCollection();

    //iterate thought the properties we get from the designer, checking to see if the setting is in the dictionary
    foreach (SettingsProperty setting in collection)
    {
        SettingsPropertyValue value = new SettingsPropertyValue(setting);
        value.IsDirty = false;

        //need the type of the value for the strong typing
        var t = Type.GetType(setting.PropertyType.FullName);

        if (SettingsDictionary.ContainsKey(setting.Name))
        {
            value.SerializedValue = SettingsDictionary[setting.Name].value;
            value.PropertyValue = Convert.ChangeType(SettingsDictionary[setting.Name].value, t);
        }
        else //use defaults in the case where there are no settings yet
        {
            value.SerializedValue = setting.DefaultValue;
            value.PropertyValue = Convert.ChangeType(setting.DefaultValue, t);
        }

            values.Add(value);
    }
    return values;
}

/// <summary>
/// Must override this, this is the bit that does the saving to file.  Called when Settings.Save() is called
/// </summary>
/// <param name="context"></param>
/// <param name="collection"></param>
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
{
    //grab the values from the collection parameter and update the values in our dictionary.
    foreach (SettingsPropertyValue value in collection)
    {
        var setting = new SettingStruct()
        {
            value = (value.PropertyValue == null ? String.Empty : value.PropertyValue.ToString()),
            name = value.Name,
            serializeAs = value.Property.SerializeAs.ToString()
        };

        if (!SettingsDictionary.ContainsKey(value.Name))
        {
            SettingsDictionary.Add(value.Name, setting);
        }
        else
        {
            SettingsDictionary[value.Name] = setting;
        }
    }

    //now that our local dictionary is up-to-date, save it to disk.
    SaveValuesToFile();
}

Complete solution. So here's the entire class which includes the constructor, Initialize, and helper methods. Feel free to cut/paste slice and dice.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Reflection;
using System.Xml.Linq;
using System.IO;

namespace YourCompany.YourProduct
{
    class CustomSettingsProvider : SettingsProvider
    {
        const string NAME = "name";
        const string SERIALIZE_AS = "serializeAs";
        const string CONFIG = "configuration";
        const string USER_SETTINGS = "userSettings";
        const string SETTING = "setting";

        /// <summary>
        /// Loads the file into memory.
        /// </summary>
        public CustomSettingsProvider()
        {
            SettingsDictionary = new Dictionary<string, SettingStruct>();

        }

        /// <summary>
        /// Override.
        /// </summary>
        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            base.Initialize(ApplicationName, config);
        }

        /// <summary>
        /// Override.
        /// </summary>
        public override string ApplicationName
        {
            get
            {
                return System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;
            }
            set
            {
                //do nothing
            }
        }

        /// <summary>
        /// Must override this, this is the bit that matches up the designer properties to the dictionary values
        /// </summary>
        /// <param name="context"></param>
        /// <param name="collection"></param>
        /// <returns></returns>
        public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
        {
            //load the file
            if (!_loaded)
            {
                _loaded = true;
                LoadValuesFromFile();
            }

            //collection that will be returned.
            SettingsPropertyValueCollection values = new SettingsPropertyValueCollection();

            //itterate thought the properties we get from the designer, checking to see if the setting is in the dictionary
            foreach (SettingsProperty setting in collection)
            {
                SettingsPropertyValue value = new SettingsPropertyValue(setting);
                value.IsDirty = false;

                //need the type of the value for the strong typing
                var t = Type.GetType(setting.PropertyType.FullName);

                if (SettingsDictionary.ContainsKey(setting.Name))
                {
                    value.SerializedValue = SettingsDictionary[setting.Name].value;
                    value.PropertyValue = Convert.ChangeType(SettingsDictionary[setting.Name].value, t);
                }
                else //use defaults in the case where there are no settings yet
                {
                    value.SerializedValue = setting.DefaultValue;
                    value.PropertyValue = Convert.ChangeType(setting.DefaultValue, t);
                }

                values.Add(value);
            }
            return values;
        }

        /// <summary>
        /// Must override this, this is the bit that does the saving to file.  Called when Settings.Save() is called
        /// </summary>
        /// <param name="context"></param>
        /// <param name="collection"></param>
        public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
        {
            //grab the values from the collection parameter and update the values in our dictionary.
            foreach (SettingsPropertyValue value in collection)
            {
                var setting = new SettingStruct()
                {
                    value = (value.PropertyValue == null ? String.Empty : value.PropertyValue.ToString()),
                    name = value.Name,
                    serializeAs = value.Property.SerializeAs.ToString()
                };

                if (!SettingsDictionary.ContainsKey(value.Name))
                {
                    SettingsDictionary.Add(value.Name, setting);
                }
                else
                {
                    SettingsDictionary[value.Name] = setting;
                }
            }

            //now that our local dictionary is up-to-date, save it to disk.
            SaveValuesToFile();
        }

        /// <summary>
        /// Loads the values of the file into memory.
        /// </summary>
        private void LoadValuesFromFile()
        {
            if (!File.Exists(UserConfigPath))
            {
                //if the config file is not where it's supposed to be create a new one.
                CreateEmptyConfig();
            }

            //load the xml
            var configXml = XDocument.Load(UserConfigPath);

            //get all of the <setting name="..." serializeAs="..."> elements.
            var settingElements = configXml.Element(CONFIG).Element(USER_SETTINGS).Element(typeof(Properties.Settings).FullName).Elements(SETTING);

            //iterate through, adding them to the dictionary, (checking for nulls, xml no likey nulls)
            //using "String" as default serializeAs...just in case, no real good reason.
            foreach (var element in settingElements)
            {
                var newSetting = new SettingStruct()
                {
                    name = element.Attribute(NAME) == null ? String.Empty : element.Attribute(NAME).Value,
                    serializeAs = element.Attribute(SERIALIZE_AS) == null ? "String" : element.Attribute(SERIALIZE_AS).Value,
                    value = element.Value ?? String.Empty
                };
                SettingsDictionary.Add(element.Attribute(NAME).Value, newSetting);
            }
        }

        /// <summary>
        /// Creates an empty user.config file...looks like the one MS creates.  
        /// This could be overkill a simple key/value pairing would probably do.
        /// </summary>
        private void CreateEmptyConfig()
        {
            var doc = new XDocument();
            var declaration = new XDeclaration("1.0", "utf-8", "true");
            var config = new XElement(CONFIG);
            var userSettings = new XElement(USER_SETTINGS);
            var group = new XElement(typeof(Properties.Settings).FullName);
            userSettings.Add(group);
            config.Add(userSettings);
            doc.Add(config);
            doc.Declaration = declaration;
            doc.Save(UserConfigPath); 
        }

        /// <summary>
        /// Saves the in memory dictionary to the user config file
        /// </summary>
        private void SaveValuesToFile()
        {
            //load the current xml from the file.
            var import = XDocument.Load(UserConfigPath);

            //get the settings group (e.g. <Company.Project.Desktop.Settings>)
            var settingsSection = import.Element(CONFIG).Element(USER_SETTINGS).Element(typeof(Properties.Settings).FullName);

            //iterate though the dictionary, either updating the value or adding the new setting.
            foreach (var entry in SettingsDictionary)
            {
                var setting = settingsSection.Elements().FirstOrDefault(e => e.Attribute(NAME).Value == entry.Key);
                if (setting == null) //this can happen if a new setting is added via the .settings designer.
                {
                    var newSetting = new XElement(SETTING);
                    newSetting.Add(new XAttribute(NAME, entry.Value.name));
                    newSetting.Add(new XAttribute(SERIALIZE_AS, entry.Value.serializeAs));
                    newSetting.Value = (entry.Value.value ?? String.Empty);
                    settingsSection.Add(newSetting);
                }
                else //update the value if it exists.
                {
                    setting.Value = (entry.Value.value ?? String.Empty);
                }
            }
            import.Save(UserConfigPath);
        }

        /// <summary>
        /// The setting key this is returning must set before the settings are used.
        /// e.g. <c>Properties.Settings.Default.SettingsKey = @"C:\temp\user.config";</c>
        /// </summary>
        private string UserConfigPath
        {
            get
            {
                return Properties.Settings.Default.SettingsKey;
            }

        }

        /// <summary>
        /// In memory storage of the settings values
        /// </summary>
        private Dictionary<string, SettingStruct> SettingsDictionary { get; set; }

        /// <summary>
        /// Helper struct.
        /// </summary>
        internal struct SettingStruct
        {
            internal string name;
            internal string serializeAs;
            internal string value;
        }

        bool _loaded;
    }
}    

这篇关于在user.config的自定义路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆