[.net] .net의 다른 어셈블리 버전에서 user.config 설정을 어떻게 유지합니까?

기본적으로 문제는 어셈블리 버전이 변경 될 때마다 (즉, 사용자가 새 버전의 응용 프로그램을 설치할 때마다) 모든 설정이 기본값을 재설정하거나 더 정확하게 다른 버전의 폴더에 새 user.config 파일이 생성된다는 것입니다 이름으로 숫자)

ini 파일이나 레지스트리를 사용하지 않는 것처럼 보이기 때문에 버전을 업그레이드 할 때 어떻게 같은 설정을 유지할 수 있습니까?

우리가 Clickonce를 사용했을 때 이것을 처리 할 수있는 것처럼 보였으므로 그렇게 할 수 있어야하는 것처럼 보이지만 어떻게 해야할지 모르겠습니다.



답변

ApplicationSettingsBase에는 이전 버전의 모든 설정을 마이그레이션하는 Upgrade라는 메소드 가 있습니다.

새 버전의 응용 프로그램을 게시 할 때마다 병합을 실행하려면 설정 파일에서 기본값이 true 인 부울 플래그를 정의 할 수 있습니다. UpgradeRequired 또는 이와 유사한 이름을 지정하십시오 .

그런 다음 응용 프로그램 시작시 플래그가 설정되어 있는지 확인하고 설정되어 있으면 Upgrade 메소드를 호출 하고 플래그를 false로 설정 한 후 구성을 저장하십시오.

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

MSDN 의 업그레이드 방법에 대해 자세히 알아보십시오 . GetPreviousVersion는 일부 사용자 정의 병합을 수행해야하는 경우도 가치가보고 될 수 있습니다.


답변

시간이 오래 걸렸습니다 … winforms 앱에서 불러 My.Settings.Upgrade()오기 전에 전화하십시오 . 현재 버전이든 이전 버전이든 최신 설정을 가져옵니다.


답변

다른 사람이 변경 / 제거 된 설정을 마이그레이션하는 데 어려움을 겪고있는 경우에 대한 나의 연구는 다음과 같습니다. 기본 문제는 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에게 감사의 마음을 전 합니다. 거기에 대한 자세한 내용을 읽을 수 있습니다.


답변

다음은 업그레이드 논리를 설정 클래스에서 파생 될 수있는 추상 클래스로 캡슐화하는 여기에 제시된 솔루션의 변형입니다.

일부 제안 된 솔루션은 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();


답변

user.settings에 대한 변경이 프로그래밍 방식으로 수행되는 경우 user.settings에 대한 수정 사본을 별도의 파일 (예 : user.customized.settings)로 유지 관리하는 것은 어떻습니까?

user.settings에서도 수정 된 설정을 유지하고로드 할 수 있습니다. 그러나이 방법으로 최신 버전의 user.settings를 사용하여 최신 버전의 응용 프로그램을 설치하면 수정 된 설정을 새 user.settings로 다시 복사하여 계속 사용할 것인지 묻는 메시지를 표시 할 수 있습니다. 도매로 가져 오거나 더 좋아져 계속 사용할 설정을 사용자에게 요청할 수 있습니다.

편집 : 어셈블리 버전에 대한 “보다 정확한”부분을 너무 빨리 읽고 새 user.settings를 새 버전 별 디렉토리에 설치합니다. 따라서 위의 아이디어가 도움이되지는 않지만 생각할만한 음식을 제공 할 수 있습니다.


답변

이것이 내가 처리 한 방법입니다.

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


답변