C# 这是否滥用了设置功能?

C# 这是否滥用了设置功能?,c#,.net,winforms,settings,C#,.net,Winforms,Settings,我一直在将用户设置的集合存储在属性.settings.Default对象中,并使用Visual Studio设置设计器(右键单击项目,单击属性,然后单击设置选项卡)来设置。最近,一些用户抱怨说,这个特定设置跟踪的数据是随机丢失的 要给出一个想法(不完全是我怎么做的,但有点接近),它的工作方式是我有一个对象,如下所示: class MyObject { public static string Property1 { get; set; } public static string

我一直在将用户设置的集合存储在
属性.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 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.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;
        }
    }
然后在代码中,我可能会这样做来保存信息:

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;
}
现在,将其拉出的代码如下所示:

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 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.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;
        }
    }
我还确保使用
[global::System.Configuration.settingsserializas(global::System.Configuration.settingsserializas.Binary)]
装饰Settings.Designer.cs文件,如下所示:

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 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.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基础设施推得太远了。我说得对吗?

从你的例子中,我看不出你的尝试有任何错误。我认为您描述的问题的根源可能是您的程序集版本更改?用户设置不会自动神奇地升级自己(至少我无法让他们升级)

我能理解你的困境,我几个月前就经历过了。我编写了一个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>


在用户作用域中使用设置功能时,设置会保存到当前登录用户的应用程序数据(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);
}
要反序列化它,请执行以下操作:

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

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

在设置设计器类中使用SettingsSerializeAs二进制属性时,我有过类似的经历。它在测试中起作用,但一段时间后它无法恢复属性值

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

我添加了以下代码来检查属性是否意外丢失,与RestoreInfo()方法相同

另外,只是因为您的示例中缺少它,所以不要忘记调用Save。调用SaveInfo()后说


不幸的是,当新版本发布时,程序集版本没有改变,设置也已经升级。这里只涉及一个用户,所以这个想法已经过时了。我很可能会以手动序列化和反序列化结束。我完全知道你的问题是什么。每当您使用GUI修改设置配置时,设计师都会抛出一个全新的文件,对您所做的所有自定义更改进行仔细检查。是的,我知道,上面有个警告,不要自己做改变,但我是说,来吧。VisualStudio团队没有充分考虑给我一个复选框来切换此选项!啊,太令人沮丧了。直到今天,我仍然有一个用户被.NET随机丢弃数据所困扰。我现在正在转向读写XML,而不是依赖.NET。@jasonh类是局部的。如果单击“设置设计器”中的“查看代码”,则会得到一个Settings.cs文件(除Settings.designer.cs外),您可以在其中进行持久更改。@Medinoc:除了这些持久更改不/不能包括属性本身的声明,您可以在其中应用
[SettingsSerializeAs]
。您对如何使用
partial
类文件持续强制该设置/属性有何建议?您不能更改现有属性,但至少可以在
ProjectName.settings
文件中添加您自己的设置。使用正确的属性,设置引擎将同样处理这些属性。