Как правильно создать во время выполнения и прочитать свойства, которые хранятся в файле конфигурации, сохраненном во время предыдущего сеанса?

Я использую этот код для создания пользовательской настройки во время выполнения:

System.Configuration.SettingsProperty userScopedProperty = 
        new System.Configuration.SettingsProperty("New Setting");

userScopedProperty.DefaultValue = "This setting default value";
userScopedProperty.IsReadOnly = false;
userScopedProperty.PropertyType = typeof(string);
userScopedProperty.Provider = 
         Properties.Settings.Default.Providers["LocalFileSettingsProvider"];

userScopedProperty.Attributes.Add(typeof(System.Configuration.UserScopedSettingAttribute), 
          new System.Configuration.UserScopedSettingAttribute());

Properties.Settings.Default.Properties.Add(userScopedProperty);
Properties.Settings.Default["New Setting"] = "value changed to this";
Properties.Settings.Default.Save();

Properties.Settings.Default.Reload();

Который почему-то работает только иногда и создаст настройки в разделе userSettings в файле user.config. При выполнении в том же сеансе это работает:

Properties.Settings.Default["New Setting"]

Но как только я закрою приложение и запущу его снова, эта строка кода даст мне System.Configuration.SettingsPropertyNotFoundException. Я пытался добавить Properties.Settings.Default.Reload() прямо перед попыткой прочитать настройку, но это тоже не работает.

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

Итак, мои вопросы: как мне правильно создать во время выполнения и прочитать свойства, которые хранятся в файле user.config, который я сохранил в предыдущем сеансе? Есть лучший способ это сделать?


person logicGate22    schedule 13.01.2021    source источник
comment
Properties.Settings.Default.Properties доступны только в текущем сеансе. Когда вы перезапустите приложение, вы увидите, что ваши настройки Default всегда совпадают с настройками, определенными в файле Settings.settings. Вы можете найти динамически добавленные свойства в файле user.config. Чтобы получить свои свойства, вы можете использовать метод, объясненный здесь.   -  person Mehdi    schedule 25.04.2021


Ответы (1)


Я обычно сохраняю такие настройки в файле XML в IsolatedStorage. Я создаю класс ProgramSettings, который я аннотирую для сериализации XML (используя XmlRootAttribute, XmlElementAttribute, а иногда и XmlArrayAttribute и XmlArrayItemAttribute), а затем использую этот класс для чтения и записи этого файла настроек XML:

public static class PersistedSettings<T> where T : class, new()
{
    public static T LoadSettings(string applicationName, ISettingsErrorReporter errorReporter)
    {
        var filename = GetFileName(applicationName);
        try
        {
            using (var isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
            {
                if (!isoStore.FileExists(filename))
                {
                    return new T();
                }
                //otherwise
                using (var settingsStream = isoStore.OpenFile(filename, FileMode.Open, FileAccess.Read))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    var settings = (T)serializer.Deserialize(settingsStream);
                    settingsStream.Close();
                    return settings;
                }
            }
        }
        catch (IOException ioException)
        {
            errorReporter.WriteError($"IO Exception:{Environment.NewLine}{ioException.Message}");
        }
        catch (Exception ex)
        {
            errorReporter.WriteError($"Exception ({ex.GetType().Name}):{Environment.NewLine}{ex.Message}");
        }
        //no matter what kind of exception, 
        return new T();
    }

    public static void SaveSettings(string applicationName, T settings, ISettingsErrorReporter errorReporter)
    {
        try
        {
            using (var isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
            {
                using (var settingsStream = isoStore.CreateFile(GetFileName(applicationName)))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    serializer.Serialize(settingsStream, settings);
                    //let's be safe and use both suspenders and a belt (Flush, Close, Dispose)
                    settingsStream.Flush();
                    settingsStream.Close();
                }
            }
        }
        catch (IOException ioException)
        {
            errorReporter.WriteError($"I/O Exception:{Environment.NewLine}{ioException.Message}");
        }
        catch (Exception ex)
        {
            errorReporter.WriteError($"Exception ({ex.GetType().Name}):{Environment.NewLine}{ex.Message}");
        }
    }

    private static string GetFileName(string applicationName)
    {
        return applicationName + ".xml";
    }
}

Я обычно использую это из простых приложений WinForms. Я заставляю свой класс Form реализовать этот интерфейс:

public interface ISettingsErrorReporter
{
    void WriteError(string message);
}

(обычно через всплывающее окно сообщения)

Затем я вызываю LoadSettings в событии FormLoad и SaveSettings в событии закрытия формы.

Это не то, что вы просите, но это может удовлетворить ваши потребности

person Flydog57    schedule 13.01.2021