代码之家  ›  专栏  ›  技术社区  ›  jasonh

这是滥用设置功能吗?

  •  2
  • jasonh  · 技术社区  · 15 年前

    我一直将用户设置集合存储在 Properties.Settings.Default 对象,然后使用Visual Studio设置设计器(右键单击项目,单击属性,然后单击设置选项卡)设置该对象。最近,一些用户抱怨这个特定设置跟踪的数据是随机丢失的。

    为了给出一个想法(不完全是我怎么做的,但有点接近),它的工作方式是我有一个对象,如:

    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; }
    }
    

    然后在代码中,我可以这样做来保存信息:

    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;
    }
    

    现在,拉出它的代码是这样的:

    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
        }
    }
    

    我还确保用 [global::System.Configuration.SettingsSerializeAs(global::System.Configuration.SettingsSerializeAs.Binary)] ,像这样:

        [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;
            }
        }
    

    现在,信息会随机消失。我可以调试这个并看到它 属性.设置.默认 正在返回空的 ArrayList 对于 SettingName .我真的不想使用数组列表,但我看不到用这种方式来存储通用集合的方法。

    我将放弃并自己使用纯XML保存这些信息。我只是想验证一下,我确实把这个.NET基础架构推得太远了。我说的对吗?

    4 回复  |  直到 14 年前
        1
  •  1
  •   jasonh    15 年前

    我找不到关于这些设置消失的原因的答案,因为我一直在这样做,我最终将这些复杂的设置分别存储在一个XML文件中,手工对它们进行序列化和反序列化。

        2
  •  1
  •   Daniel Ballinger    14 年前

    在设置设计器类中使用settingsSerializeas二进制属性时,我有非常类似的经验。它在测试中起作用,但过了一段时间,未能恢复属性值。

    在我的例子中,随后通过设计器对设置进行了添加。源代码管理历史记录显示,在我不知道的情况下,已从settings.designer.cs中删除了settingsSerializeas属性。

    我添加了以下代码来检查属性是否意外地丢失了与restoreinfo()方法等效的属性。

    #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
    

    另外,只因为示例中缺少它,所以不要忘记调用save。调用saveinfo()后说。

    Properties.Settings.Default.Save();
    
        3
  •  0
  •   user153498    15 年前

    在用户作用域中使用设置功能时,设置将保存到当前登录用户的应用程序数据(vista/7中的appdata)文件夹中。所以如果usera登录,使用你的应用程序,然后userb登录,他就不会加载usera的设置,他会有自己的设置。

    在你试图实现的目标中,我建议使用 XmlSerializer 用于序列化对象列表的类。使用非常简单:

    要序列化它:

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

    要反序列化它:

    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);
    }
    
        4
  •  0
  •   csharptest.net    14 年前

    从你的例子中,我没有看到任何关于你试图做什么的错误。我认为您描述的问题的根源可能是您的程序集版本更改?用户设置不会自动神奇地自我升级(至少我不能让它们自动升级)。

    我能理解你的困境,几个月前我经历过。我编写了一个用户设置类,该类在一个命名的组标题下提供标准的名称/值对集合(keyValueConfigurationElement),如下所示:

    <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>
    

    不管怎样,看看这是否满足您的需要,或者提供一些关于实现自定义配置部分的见解,以允许您需要什么。

    哦,是的,代码在这里:

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