development

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

big-blog 2020. 6. 27. 10:09
반응형

.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는 일부 사용자 정의 병합을 수행해야하는 경우도 가치가보고 될 수 있습니다.


다른 사람이 변경 / 제거 된 설정을 마이그레이션하는 데 어려움을 겪고있는 경우에 대한 나의 연구는 다음과 같습니다. 기본 문제는 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에서이 클래스의 이름 MySettingsMy네임 스페이스 에서 사용할 수 있습니다 . 부분 클래스 기능을 사용하여 더 이상 사용되지 않는 설정이 현재 설정과 섞이지 않도록 할 수 있습니다.

이 문제에 대한 훌륭한 기사 를 게시 해 주신 jsharrison에게 감사의 마음을 전 합니다. 거기에 대한 자세한 내용을 읽을 수 있습니다.


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


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

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

If your changes to user.settings are done programmatically, how about maintaining a copy of (just) the modifications to user.settings in a separate file, e.g. user.customized.settings?

You probably still want to maintain and load the modified settings in user.settings as well. But this way when you install a newer version of your application with its newer version of user.settings you can ask the user if they want to continue to use their modified settings by copying them back into the new user.settings. You could import them wholesale, or get fancier and ask the user to confirm which settings they want to continue to use.

EDIT: I read too quickly over the "more accurately" part about assembly versions causing a new user.settings to be installed into a new version-specific directory. Thus, the idea above probably doesn't help you, but may provide some food for thought.


This is how I handled it:

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;

}

and in the settings class, I defined the IsDefault property:

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

In the SaveSettings, I set IsDefault to 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();
}

참고URL : https://stackoverflow.com/questions/534261/how-do-you-keep-user-config-settings-across-different-assembly-versions-in-net

반응형