2009-10-06 59 views
2

我一直在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 
    } 
} 

我也确信装饰Settings.Designer.cs与[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; 
     } 
    } 

现在,随机,信息就会消失。我可以调试,看到Properties.Settings.Default正在为SettingName返回一个空的ArrayList。我真的不想使用ArrayList,但我没有看到以这种方式获取泛型集合的方法。

我即将放弃并使用纯XML保存这些信息。我只是想验证我确实推动了这一点.NET基础设施。我对吗?

回答

1

我无法找到一个答案,为什么这些设置消失,因为我一直在发生时,我最终将一组复杂的设置分别存储在一个XML文件中,手动序列化和反序列化它们。

0

从你的例子,我没有看到你想要做什么不正确。我认为你描述的问题的根源可能是你的程序集版本改变了?用户设置不会自动升级自己(至少我不能让他们)。

我可以欣赏你的困境,几个月前我经历了这个。我下了一个名为组编写了所提供的标准名称/值对集合一个UserSettings类(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> 

反正看是否符合您的需求,或者提供一些见解,实现自定义的ConfigurationSection以允许你需要的东西。

哦,是啊,代码是在这里:

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

+0

不幸的是,汇编版本没有改变,当新版本发布时,设置已经升级。 – jasonh 2009-10-07 01:11:03

0

当使用设置与用户范围功能,将设置保存到当前登录的用户的Application Data(应用程序数据在Vista/7)夹。因此,如果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); 
} 
+0

只有一个用户参与到这里,让这个主意出来了。我很可能最终会使用手动序列化和反序列化。 – jasonh 2009-10-07 01:11:43

1

在设置设计器类中使用SettingsSerializeAs二进制属性时,我的体验非常相似。它在测试中工作,但一段时间后,它无法恢复属性值。

在我的情况下,后来通过设计人员添加了设置。源代码管理历史记录显示,SettingsSerializeAs属性在我不知情的情况下已从Settings.Designer.cs中删除。

我添加了下面的代码来检查该属性没有被意外丢失,它与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(); 
+1

我确切地知道你的问题是什么。每当您使用GUI修改设置配置时,设计人员都会吐出一个*全新*新文件,翻阅您所做的所有自定义更改。是的,我知道,顶部有一个警告,不要自己改变,但我的意思是,来吧。 Visual Studio团队没有充分考虑给我一个复选框来切换这个!呃,太令人沮丧了。直到今天,我仍然有*一个*用户受到.NET的影响而随机丢弃他的数据。我现在正在转向使用XML进行读写,而不是依赖于.NET。 – jasonh 2011-02-14 23:10:24

+0

@jasonh班级是部分班级。如果您在设置设计器中单击“查看代码”,则会得到Settings.cs文件(除了Settings.Designer.cs),您可以在其中进行持久更改。 – Medinoc 2014-10-03 08:30:08

+0

@Medinoc:除了那些持久性变化不包含属性本身的声明,其中一个会应用'[SettingsSerializeAs]'。你有没有建议如何使用'partial'类文件来持久地强制设置/属性? – 2015-07-23 00:26:13