Is this an abuse of the settings function?

I am saving collections of custom preferences in an object Properties.Settings.Default

and using the Visual Studio Options Designer (right click on my project, click Properties and then go to the Preferences tab) to set this. Lately, several users have complained that the data given in this track is missing, randomly.

To give an idea (not exactly the way I do it, but somewhat close) how it works, I have an object, for example:

class MyObject
{
    public static string Property1 { get; set; }
    public static string Property2 { get; set; }
    public static string Property3 { get; set; }
    public static string Property4 { get; set; }
}

      

Then in code, I can do something like this to save the information:

public void SaveInfo()
{
    ArrayList userSetting = new ArrayList();
    foreach (Something s in SomeCollectionHere) // For example, a ListView contains the info
    {
        MyObject o = new MyObject {
            Property1 = s.P1;
            Property2 = s.P2;
            Property3 = s.P3;
            Property4 = s.P4;
        };
        userSetting.Add(o);
    }
    Properties.Settings.Default.SettingName = userSetting;
}

      

Now the code to pull it out looks something like this:

public void RestoreInfo()
{
    ArrayList setting = Properties.Settings.Default.SettingName;

    foreach (object o in setting)
    {
        MyObject data = (MyObject)o;
        // Do something with the data, like load it in a ListView
    }
}

      

I also made sure to decorate the Settings.Designer.cs file with [global::System.Configuration.SettingsSerializeAs(global::System.Configuration.SettingsSerializeAs.Binary)]

, for example:

    [global::System.Configuration.UserScopedSettingAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Configuration.SettingsSerializeAs(global::System.Configuration.SettingsSerializeAs.Binary)]
    public global::System.Collections.ArrayList SettingName
    {
        get {
            return ((global::System.Collections.ArrayList)(this["SettingName"]));
        }
        set {
            this["SettingName"] = value;
        }
    }

      

Now, in random order, the information will disappear. I can debug this and see what Properties.Settings.Default

returns empty ArrayList

for SettingName

. I would rather not use an ArrayList, but I see no way to get a generic collection to store this way.

I'm going to opt out and store this information using plain XML myself. I just wanted to check that I was really pushing this bit of .NET framework too much. I'm right?

+2


source to share


4 answers


I couldn't find an answer as to why these parameters are disappearing, and since I kept happening, I ended up keeping the complex sets of parameters separately in an XML file, manually serializing and deserializing them myself.



+1


source


I had a very similar experience using the SettingsSerializeAs binary attribute in the Designer class. He worked in testing, but after a while he was unable to recover the property values.

In my case, additions were added to the settings made through the constructor. Version control history has shown that the SettingsSerializeAs attribute has been removed from Settings.Designer.cs without my knowledge.

I added the following code to ensure that this attribute was not accidentally lost as the equivalent of the RestoreInfo () method.



#if(DEBUG)
                //Verify that the Property has the required attribute for Binary serialization.
                System.Reflection.PropertyInfo binarySerializeProperty = Properties.Settings.Default.GetType().GetProperty("SettingName");
                object[] customAttributes = binarySerializeProperty.GetCustomAttributes(typeof(System.Configuration.SettingsSerializeAsAttribute), false);
                if (customAttributes.Length != 1)
                {
                    throw new ApplicationException("SettingsSerializeAsAttribute required for SettingName property");
                }
#endif

      

Also, just because it is missing from your example, don't forget to call Save. Let's say after calling SaveInfo ().

Properties.Settings.Default.Save();

      

+1


source


From your example, I see nothing wrong with what you are trying to do. I think the root of the problem you are describing could be changed by your version of the assembly? The custom settings don't automatically activate themselves (at least I couldn't get them).

I can appreciate your position, I went through this a few months ago. I coded up a UserSettings class that provided the standard collections of name / value pairs (KeyValueConfigurationElement) under a named group header, something like the following:

<configSections>
  <section name="userSettings" type="CSharpTest.Net.AppConfig.UserSettingsSection, CSharpTest.Net.Library"/>
</configSections>
<userSettings>
  <add key="a" value="b"/>
  <sections>
    <section name="c">
      <add key="a" value="y"/>
    </section>
  </sections>
</userSettings>

      

Either way, make sure it suits your needs or provides some insight into the implementation of a custom ConfigurationSection to resolve what you need.

Oh yes, the code is here:

http://csharptest.net/browse/src/Library/AppConfig

0


source


When using the "Settings" function in the "User" area, the settings are saved in the current "Application Data" folder (AppData in Vista / 7). So if UserA logged in, used your application and then UserB logged in, it would not have UserA settings, it would have its own.

In what you are trying to accomplish, I would suggest using a class XmlSerializer

to serialize a list of objects. The usage is pretty simple:

For serialization:

ArrayList list = new ArrayList();
XmlSerializer s = new XmlSerializer(typeof(ArrayList));
using (FileStream fs = new FileStream(@"C:\path\to\settings.xml", FileMode.OpenOrCreate))
{
    s.Serialize(fs, list);
}

      

To deserialize:

ArrayList list;
XmlSerializer s = new XmlSerializer(typeof(ArrayList));
using (FileStream fs = new FileStream(@"C:\path\to\settings.xml", FileMode.Open))
{
    list = (ArrayList)s.Deserialize(fs);
}

      

0


source







All Articles