Application Settings
От: altarvic  
Дата: 16.01.07 11:54
Оценка:
привет!
Как известно, во втором .NET появилась возможность легко хранить настройки приложения в .config файлах, используя для этого студию и класс ApplicationSettingsBase. Для простых типов, все работает на ура. Мне не удалось заставить сохранять список моих собственных классов:

[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator","8.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

 [global::System.Configuration.UserScopedSettingAttribute()]
 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
 public global::System.Collections.ArrayList test {
  get { return ((global::System.Collections.ArrayList)(this["test"])); }
  set { this["test"] = value; }    
 }
}


ArrayList хранит объекты следующего типа:
    public sealed class Test
    {
        public int i = 3;
        public Test() { }
    }


Но не сохраняется этот список, не могу понять почему. Если в ArrayList пихать строки или числа, то сохраняется. В доках написано что используется xml сериализация, но видимо ApplicationSettingBase плевать на ограничения, связанные с ней. Т.е. если я объявлю мой класс так:


    public sealed class Test
    {
        [NonSerialized]
        public int i = 1;
    }

[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator","8.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

 [global::System.Configuration.UserScopedSettingAttribute()]
 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
 public Test test {
  get { return ((Test)(this["test"])); }
  set { this["test"] = value; }    
 }
}

то значения с успехом запишутся без всяких ошибок.
Вобщем везде одна засада, жду ваших комментариев

p.s. про другие способы сериализации в курсе, но хочется использовать штатные средства
Re: Application Settings
От: SiAVoL Россия  
Дата: 16.01.07 13:05
Оценка:
Здравствуйте, altarvic, Вы писали:

A>ArrayList хранит объекты следующего типа:

A>
A>    public sealed class Test
A>    {
A>        public int i = 3;
A>        public Test() { }
A>    }
A>


A>Но не сохраняется этот список, не могу понять почему.

Класс Test необходимо пометить атрбутом Serializable.

A>В доках написано что используется xml сериализация, но видимо ApplicationSettingBase плевать на ограничения, связанные с ней. Т.е. если я объявлю мой класс так:


A>[c#]

A> public sealed class Test
A> {
A> [NonSerialized]
A> public int i = 1;
A> }
не плевать. Атрибут NonSerialized не относится к Xml-сериализации. Для этого надо использовать атрибут XmlIgnore.

A>Вобщем везде одна засада, жду ваших комментариев

да нет там засады Более того, можно написать свое представление с помощью TypeConverter. А так же привинтить редактор значений этого класса, который можно будет использовать в студийном редакторе настроек, с помощью атрибута Editor.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[2]: Application Settings
От: vitz  
Дата: 16.01.07 13:28
Оценка:
Здравствуйте, SiAVoL, Вы писали:

SAV>Здравствуйте, altarvic, Вы писали:


A>>ArrayList хранит объекты следующего типа:

A>>
A>>    public sealed class Test
A>>    {
A>>        public int i = 3;
A>>        public Test() { }
A>>    }
A>>


A>>Но не сохраняется этот список, не могу понять почему.

SAV>Класс Test необходимо пометить атрбутом XmlSerializable
Re[2]: Application Settings
От: altarvic  
Дата: 17.01.07 04:55
Оценка:
Здравствуйте, SiAVoL, Вы писали:

A>>Но не сохраняется этот список, не могу понять почему.

SAV>Класс Test необходимо пометить атрбутом Serializable.

Это не помогает, проверил.
Если ArrayList хранит список классов Test, то ничего в итоге не сохраняется. Если список заполнить простыми типами (строки, числа) то сохраняет (независимо от атрибута Serializable)

SAV>не плевать. Атрибут NonSerialized не относится к Xml-сериализации. Для этого надо использовать атрибут XmlIgnore.


Да, ты прав, с XmlIgnore все нормально

A>>Вобщем везде одна засада, жду ваших комментариев

SAV>да нет там засады Более того, можно написать свое представление с помощью TypeConverter.

Но это же будет в виде одной строки храниться? Я хотел именно в виде xml, поскольку класс Test показан для примера, он может быть достаточно объемным.


A>>А так же привинтить редактор значений этого класса, который можно будет использовать в студийном редакторе настроек, с помощью атрибута Editor.


Это не критично для меня
Re[3]: Application Settings
От: altarvic  
Дата: 17.01.07 09:25
Оценка:
Хочу еще добавить, что затык как-то связан именно с xml сериализацией, поскольку если для свойства выставить тип сериализации как
[SettingsSerializeAs(SettingsSerializeAs.Binary)] то все прекрастно работает (и в случае отсутствия атрибута [Serializable] ругается, что правильно)

p.s. Что никто не использует ApplicationBaseSettings ? Это же самый удобный и быстрый способ сохранения настроек!
Re[4]: Application Settings
От: oleksab Украина  
Дата: 17.01.07 11:13
Оценка:
Здравствуйте, altarvic, Вы писали:

A>p.s. Что никто не использует ApplicationBaseSettings ? Это же самый удобный и быстрый способ сохранения настроек!


Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re: Application Settings
От: jenyavb  
Дата: 06.02.07 13:40
Оценка:
Здравствуйте, altarvic, Вы писали:

Ну что нашел решение? Если да, то скажи как это сделать, плз.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Application Settings
От: jenyavb  
Дата: 06.02.07 13:41
Оценка:
Здравствуйте, oleksab, Вы писали:

O>Здравствуйте, altarvic, Вы писали:


A>>p.s. Что никто не использует ApplicationBaseSettings ? Это же самый удобный и быстрый способ сохранения настроек!


O> Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.


Как это сделать, примерчика не будет?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Application Settings
От: oleksab Украина  
Дата: 06.02.07 16:05
Оценка:
Здравствуйте, jenyavb, Вы писали:

O>> Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.


J>Как это сделать, примерчика не будет?


у меня есть примерчики, но их долго выдерать из рабочего кода
попробуй Google-ом поискать, если не получиться — буду выдирать.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[7]: Application Settings
От: jenyavb  
Дата: 08.02.07 05:36
Оценка:
Здравствуйте, oleksab, Вы писали:

O>Здравствуйте, jenyavb, Вы писали:


O>>> Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.


J>>Как это сделать, примерчика не будет?


O>у меня есть примерчики, но их долго выдерать из рабочего кода

O>попробуй Google-ом поискать, если не получиться — буду выдирать.

Я вот что-то не вкуриваю: ConfigurationElement относится к ApplicationSettings (Propertyes.Settings...) или к конфигу приложения (где можно прописать ConnectionStrings, указать версию рентайма и т.п.)?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: Application Settings
От: oleksab Украина  
Дата: 08.02.07 08:06
Оценка: 2 (1)
Здравствуйте, jenyavb, Вы писали:

J>Я вот что-то не вкуриваю: ConfigurationElement относится к ApplicationSettings (Propertyes.Settings...) или к конфигу приложения (где можно прописать ConnectionStrings, указать версию рентайма и т.п.)?


наверное, все-таки к конфигу приложения, потому что настройки добавляются через custom section и потом их нужно вручную вычитывать с помощью
                    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                    _current = (Settings)config.GetSection(sectionName);
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[9]: Application Settings
От: jenyavb  
Дата: 08.02.07 09:58
Оценка:
Здравствуйте, oleksab, Вы писали:

Жаль... Как же сохранять эти гребаные настроийки...? Придется свои делать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[10]: Application Settings
От: oleksab Украина  
Дата: 08.02.07 15:25
Оценка:
Здравствуйте, jenyavb, Вы писали:

J>Жаль... Как же сохранять эти гребаные настроийки...? Придется свои делать.


это проще всего
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                config.Sections.Remove(sectionName);
                config.Sections.Add(sectionName, new Settings(_current)); // получить новый экземпляр, с помощью конструктора копии
                config.Save(ConfigurationSaveMode.Full);

где Settings — сам класс наследник от ConfigurationSection а _current — вычитанные настройки из конфига
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[11]: Application Settings
От: jenyavb  
Дата: 09.02.07 08:04
Оценка:
Здравствуйте, oleksab, Вы писали:

O>Здравствуйте, jenyavb, Вы писали:


J>>Жаль... Как же сохранять эти гребаные настроийки...? Придется свои делать.


O>это проще всего

O>
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
O>                config.Sections.Remove(sectionName);
O>                config.Sections.Add(sectionName, new Settings(_current)); // получить новый экземпляр, с помощью конструктора копии
O>                config.Save(ConfigurationSaveMode.Full);
O>

O>где Settings — сам класс наследник от ConfigurationSection а _current — вычитанные настройки из конфига

А куда они сохраняются?

Да и хотелось бы сделать с новыми настрийками...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: Application Settings
От: oleksab Украина  
Дата: 09.02.07 08:48
Оценка: 3 (1)
Здравствуйте, jenyavb, Вы писали:

O>>это проще всего

O>>
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
O>>                config.Sections.Remove(sectionName);
O>>                config.Sections.Add(sectionName, new Settings(_current)); // получить новый экземпляр, с помощью конструктора копии
O>>                config.Save(ConfigurationSaveMode.Full);
O>>

O>>где Settings — сам класс наследник от ConfigurationSection а _current — вычитанные настройки из конфига

J>А куда они сохраняются?


в имя_проекта.exe.config, куда же еще?

J>Да и хотелось бы сделать с новыми настрийками...


слушай, ты даже мертвого уговоришь
это app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="TestSettingsClass" type="Test.Settings.TestSettingsClass, TestAssembly" restartOnExternalChanges="true" />
  </configSections>
  <TestSettingsClass UnknownCity="374" UnknownStreet="unk street" UnknownCountry="UA" UnknownRegion="81" UnknownZipCode="0001" WorldRegion="1">
    <Database Server="servername" File="d:\test.fdb" Dialect="1" User="sysdba" Password="masterkey" Charset="WIN1251" Pooling="False"/>
  </TestSettingsClass>
</configuration>

это классы обертки над настройками
using System;
using System.Configuration;
using System.Reflection;
using System.IO;

namespace Test.Settings
{
    /// <summary>
    /// holds settings for TestSettingsClass client export
    /// </summary>
    public class TestSettingsClass : ConfigurationSection
    {
        private static TestSettingsClass _current = null;
        public const string sectionName = "TestSettingsClass";

        public static TestSettingsClass Current
        {
            get
            {
                if (_current == null)
                {
                    Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
                    _current = (TestSettingsClass)config.GetSection(sectionName);

                    FileWatcher.StartWatching(ConfigFile_Changed);
                }
                return _current;
            }
        }

        private static void ConfigFile_Changed(object sender, FileSystemEventArgs e)
        {
            ConfigurationManager.RefreshSection(sectionName);
            Log.Info("{0} section has been reloaded", sectionName);
            _current = (TestSettingsClass)ConfigurationManager.GetSection(sectionName);
        }

        private const string DatabaseName = "Database";
        [ConfigurationProperty(DatabaseName)]
        public Database Database
        {
            get { return (Database)this[DatabaseName]; }
        }

        private const string UnknownCityName = "UnknownCity";
        [ConfigurationProperty(UnknownCityName)]
        public string UnknownCity
        {
            get { return (string) this[UnknownCityName]; }
        }

        private const string UnknownStreetName = "UnknownStreet";
        [ConfigurationProperty(UnknownStreetName)]
        public string UnknownStreet
        {
            get { return (string)this[UnknownStreetName]; }
        }

        private const string UnknownCountryName = "UnknownCountry";
        [ConfigurationProperty(UnknownCountryName)]
        public string UnknownCountry
        {
            get { return (string) this[UnknownCountryName]; }
        }

        private const string UnknownRegionName = "UnknownRegion";
        [ConfigurationProperty(UnknownRegionName)]
        public string UnknownRegion
        {
            get { return (string)this[UnknownRegionName]; }
        }

        private const string UnknownZipCodeName = "UnknownZipCode";
        [ConfigurationProperty(UnknownZipCodeName)]
        public string UnknownZipCode
        {
            get { return (string) this[UnknownZipCodeName]; }
        }

        private const string WorldRegionName = "WorldRegion";
        [ConfigurationProperty(WorldRegionName)]
        public string WorldRegion
        {
            get { return (string)this[WorldRegionName]; }
        }
    }

    public class Database : ConfigurationElement
    {
        public const string ServerName = "Server";
        [ConfigurationProperty(ServerName, DefaultValue = "server could not be read")]
        public string Server
        {
            get { return (string)this[ServerName]; }
            set { this[ServerName] = value; }
        }

        public const string DatabaseName = "File";
        [ConfigurationProperty(DatabaseName, DefaultValue = "database could not be read")]
        public string File
        {
            get { return (string)this[DatabaseName]; }
            set { this[DatabaseName] = value; }
        }

        public const string UserName = "User";
        [ConfigurationProperty(UserName, DefaultValue = "user could not be read")]
        public string User
        {
            get { return (string)this[UserName]; }
            set { this[UserName] = value; }
        }

        public const string PasswordName = "Password";
        [ConfigurationProperty(PasswordName, DefaultValue = "password could not be read")]
        public string Password
        {
            get { return (string)this[PasswordName]; }
            set { this[PasswordName] = value; }
        }

        public const string DialectName = "Dialect";
        [ConfigurationProperty(DialectName, DefaultValue = "1")]
        public string Dialect
        {
            get { return (string)this[DialectName]; }
            set { this[DialectName] = value; }
        }

        public const string RoleName = "Role";
        [ConfigurationProperty(RoleName, DefaultValue = "")]
        public string Role
        {
            get { return (string)this[RoleName]; }
            set { this[RoleName] = value; }
        }

        public const string CharsetName = "Charset";
        [ConfigurationProperty(CharsetName, DefaultValue = "")]
        public string Charset
        {
            get { return (string)this[CharsetName]; }
            set { this[CharsetName] = value; }
        }

        public const string PoolingName = "Pooling";
        [ConfigurationProperty(PoolingName, DefaultValue = true)]
        public bool Pooling
        {
            get { return (bool)this[PoolingName]; }
            set { this[PoolingName] = value; }
        }
    }
}

но это без возможности сохранения.
чтобы можно было сохранять, нужно написать код, аналогичный приведенному в предидущем сообщении.
пользоваться например так:
Console.WriteLine(TestSettingsClass.Current.UnknownCountry);
if(TestSettingsClass.Current.Database.Pooling)
    Console.WriteLine("pooling enabled");


PS код выдран из рабочего, так что втупую может не компилиться.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[13]: Application Settings
От: jenyavb  
Дата: 09.02.07 10:23
Оценка:
Здравствуйте, oleksab, Вы писали:

J>>А куда они сохраняются?


O>в имя_проекта.exe.config, куда же еще?


В папку приложения? А если нет прав?

O>слушай, ты даже мертвого уговоришь


Я? уговаривал? тебя?

Спасибо за примерчик! И за потраченное время!
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[14]: Application Settings
От: oleksab Украина  
Дата: 09.02.07 13:47
Оценка:
Здравствуйте, jenyavb, Вы писали:

J>>>А куда они сохраняются?


O>>в имя_проекта.exe.config, куда же еще?


J>В папку приложения? А если нет прав?


Значит не сохраняться, что ж еще может быть?
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[14]: Application Settings
От: oleksab Украина  
Дата: 09.02.07 15:13
Оценка:
Здравствуйте, jenyavb, Вы писали:

J>>>А куда они сохраняются?


O>>в имя_проекта.exe.config, куда же еще?


J>В папку приложения? А если нет прав?


Забыл — если нужно хранить настройки, спецефичные для пользователя, то можно хранить их где-то в дебрях ApplicationData пользовательского профайла — но тогда эти настройки нужно вычитывать из ConfigurationUserLevel.PerUserRoamingAndLocal по-моему. И сохранять соответственно. Но я так никогда не делал — так что нужно будет самому изыскивать возможности.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[4]: Application Settings
От: Аноним  
Дата: 17.01.07 11:43
Оценка:
Все должно нормально сериализоваться в xml. Добавь атрибут [SettingsSerializeAs(SettingsSerializeAs.Xml)] в Settings файл у своего элемента настроек и все будет "пучком" Единственное, что может усложнять ситуацию, так это использование ArrayList'a. Попробуй сделать вместо него List<Test>. Должно помочь.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.