Как сохранить настройки user.config для разных версий сборки в .net? - PullRequest
129 голосов
/ 11 февраля 2009

В основном проблема заключается в том, что каждый раз при изменении версии сборки (т. Е. Пользователь устанавливает новую версию приложения) все их настройки сбрасываются по умолчанию (или, точнее, создается новый файл user.config в папке с другой номер версии в качестве имени)

Как сохранить те же настройки при обновлении версий, поскольку использование INI-файлов или реестра не рекомендуется?

Когда мы использовали Clickonce, казалось, что он мог справиться с этим, поэтому кажется, что это должно быть в состоянии сделать, но я не уверен, как.

Ответы [ 6 ]

215 голосов
/ 11 февраля 2009

ApplicationSettingsBase имеет метод с именем Upgrade , который переносит все настройки из предыдущей версии.

Чтобы выполнять слияние при публикации новой версии приложения, вы можете определить логический флаг в файле настроек, который по умолчанию имеет значение true. Назовите его UpgradeRequired или что-то подобное.

Затем при запуске приложения вы проверяете, установлен ли флаг, и если он установлен, вызовите Метод обновления , установите для флага значение false и сохраните свою конфигурацию.

if (Settings.Default.UpgradeRequired)
{
    Settings.Default.Upgrade();
    Settings.Default.UpgradeRequired = false;
    Settings.Default.Save();
}

Подробнее о методе обновления читайте по адресу MSDN . GetPreviousVersion также стоит посмотреть, если вам нужно выполнить какое-то пользовательское объединение.

1 голос
/ 21 января 2018

Ниже представлен вариант решений, представленных здесь, которые инкапсулируют логику обновления в абстрактный класс, из которого могут наследовать классы настроек.

Некоторые предлагаемые решения используют атрибут DefaultSettingsValue для указания значения, которое указывает, когда предыдущие настройки не были загружены. Я предпочитаю просто использовать тип, значение которого по умолчанию указывает на это. В качестве бонуса, DateTime? полезна отладочная информация.

public abstract class UserSettingsBase : ApplicationSettingsBase
{
    public UserSettingsBase() : base()
    {
        // Accessing a property attempts to load the settings for this assembly version
        // If LastSaved has no value (default) an upgrade might be needed
        if (LastSaved == null)
        {
            Upgrade();
        }
    }

    [UserScopedSetting]
    public DateTime? LastSaved
    {
        get { return (DateTime?)this[nameof(LastSaved)]; }
        private set { this[nameof(LastSaved)] = value; }
    }

    public override void Save()
    {
        LastSaved = DateTime.Now;
        base.Save();
    }
}

Производные от UserSettingsBase:

public class MySettings : UserSettingsBase
{
    [UserScopedSetting]
    public string SomeSetting
    {
        get { return (string)this[nameof(SomeSetting)]; }
        set { this[nameof(SomeSetting)] = value; }
    }

    public MySettings() : base() { }
}

И используйте это:

// Existing settings are loaded and upgraded if needed
MySettings settings = new MySettings();
...
settings.SomeSetting = "SomeValue";
...
settings.Save();
1 голос
/ 13 апреля 2016

Вот мое исследование на случай, если кому-то еще будет трудно перенести настройки, которые были изменены / удалены. Основная проблема в том, что GetPreviousVersion() не работает, если вы переименовали или удалили параметр в новой версии вашего приложения. Поэтому вам нужно сохранить настройку в своем классе Settings, но добавить к ней несколько атрибутов / артефактов, чтобы вы случайно не использовали ее в коде в другом месте, что делает его устаревшим. Пример устаревшей настройки в VB.NET будет выглядеть следующим образом (может быть легко переведен на C #):

<UserScopedSetting(),
DebuggerNonUserCode(),
DefaultSettingValue(""),
Obsolete("Do not use this property for any purpose. Use YOUR_NEW_SETTING_NAME instead."),
NoSettingsVersionUpgrade()>
Public Property OldSettingName() As String
  Get
    Throw New NotSupportedException("This property is obsolete")
  End Get
  Set
    Throw New NotSupportedException("This property is obsolete")
  End Set
End Property

Убедитесь, что вы добавили это свойство в то же пространство имен / класс, в котором находятся настройки вашего приложения. В VB.NET этот класс называется MySettings и доступен в My пространстве имен. Вы можете использовать частичную функциональность класса, чтобы предотвратить смешивание устаревших настроек с текущими настройками.

Полная благодарность jsharrison за публикацию превосходной статьи об этой проблеме. Подробнее об этом можно прочитать там.

1 голос
/ 13 марта 2016

Я знаю, что это было некоторое время ... В приложении winforms просто позвоните My.Settings.Upgrade(), прежде чем загружать их. Это позволит получить последние настройки, будь то текущая версия или предыдущая версия.

0 голосов
/ 11 мая 2015

Вот как я справился:

public virtual void LoadSettings(ServiceFileFormBaseSettings settings = null, bool resetSettingsToDefaults = false)
{
    if (settings == null)
            return;

    if (resetSettingsToDefaults)
        settings.Reset();
    else
    {
        settings.Reload();

        if (settings.IsDefault)
            settings.Upgrade();
    }

    this.Size = settings.FormSize;

}

и в классе настроек я определил свойство IsDefault:

// SaveSettings always sets this to be FALSE.
// This will have the default value TRUE when first deployed, or immediately after an upgrade.
// When the settings exist, this is false.
//
[UserScopedSettingAttribute()]
[DefaultSettingValueAttribute("true")]
public virtual bool IsDefault
{
    get { return (bool)this["IsDefault"]; }
    set { this["IsDefault"] = value; }
}

В SaveSettings я установил для IsDefault значение false:

public virtual void SaveSettings(ServiceFileFormBaseSettings settings = null)
{
    if (settings == null) // ignore calls from this base form, if any
        return;

    settings.IsDefault = false;
    settings.FormSize = this.Size;
    settings.Save();
}
0 голосов
/ 11 февраля 2009

Если ваши изменения в user.settings сделаны программно, как насчет сохранения копии (просто) изменений в user.settings в отдельном файле, например, user.customized.settings

Возможно, вы все еще хотите сохранить и загрузить измененные настройки в user.settings. Но таким образом, когда вы устанавливаете более новую версию своего приложения с более новой версией user.settings, вы можете спросить пользователя, хотят ли они продолжать использовать свои измененные настройки, скопировав их обратно в новый user.settings. Вы можете импортировать их оптом или стать более любопытными и попросить пользователя подтвердить, какие настройки они хотят продолжать использовать.

РЕДАКТИРОВАТЬ: я читаю слишком быстро «более точную» часть о версиях сборки, в результате чего новые user.settings устанавливаются в новый каталог для конкретной версии. Таким образом, идея выше, вероятно, не поможет вам, но может дать пищу для размышлений.

...