Это злоупотребление функцией настроек? - PullRequest
2 голосов
/ 07 октября 2009

Я храню коллекции пользовательских настроек в объекте 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 возвращает пустой ArrayList для SettingName. Я действительно не хотел бы использовать ArrayList, но я не вижу способа получить универсальную коллекцию для хранения таким способом.

Я собираюсь сдаться и сохранить эту информацию, используя простой XML самостоятельно. Я просто хотел убедиться, что я действительно слишком далеко продвигался к этой части .NET-инфраструктуры. Я прав?

Ответы [ 4 ]

1 голос
/ 14 февраля 2011

У меня был очень похожий опыт при использовании двоичного атрибута 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

Кроме того, только потому, что это отсутствует в вашем примере, не забудьте позвонить Сохранить. Скажите после вызова SaveInfo ().

Properties.Settings.Default.Save();
1 голос
/ 09 ноября 2009

Я не мог найти ответ относительно того, почему эти настройки исчезали, и, поскольку я продолжал происходить, я закончил хранить сложные наборы настроек отдельно в файле XML, вручную сериализовывая и десериализуя их.

0 голосов
/ 07 октября 2009

При использовании функции «Настройки» в области «Пользователь» настройки сохраняются в папке «Данные приложения» (AppData in Vista / 7), которая в данный момент зарегистрирована. Поэтому, если пользователь А вошел в систему, использовал ваше приложение, а затем вошел в систему пользователь В, у него не было бы загруженных настроек пользователя А, у него были бы его собственные.

В том, что вы пытаетесь выполнить, я бы предложил использовать класс 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 голосов
/ 07 октября 2009

Из вашего примера я не вижу ничего неправильного в том, что вы пытаетесь сделать. Я думаю, что корень проблемы, которую вы описываете, может быть изменением вашей версии сборки? Пользовательские настройки не обновляются автоматически (по крайней мере, я не могу их получить).

Я могу оценить твое положение, я прошел через это несколько месяцев назад. Я кодировал класс 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

...