привет!
Как известно, во втором .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. про другие способы сериализации в курсе, но хочется использовать штатные средства
Здравствуйте, 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.
Здравствуйте, SiAVoL, Вы писали:
A>>Но не сохраняется этот список, не могу понять почему. SAV>Класс Test необходимо пометить атрбутом Serializable.
Это не помогает, проверил.
Если ArrayList хранит список классов Test, то ничего в итоге не сохраняется. Если список заполнить простыми типами (строки, числа) то сохраняет (независимо от атрибута Serializable)
SAV>не плевать. Атрибут NonSerialized не относится к Xml-сериализации. Для этого надо использовать атрибут XmlIgnore.
Да, ты прав, с XmlIgnore все нормально
A>>Вобщем везде одна засада, жду ваших комментариев SAV>да нет там засады Более того, можно написать свое представление с помощью TypeConverter.
Но это же будет в виде одной строки храниться? Я хотел именно в виде xml, поскольку класс Test показан для примера, он может быть достаточно объемным.
A>>А так же привинтить редактор значений этого класса, который можно будет использовать в студийном редакторе настроек, с помощью атрибута Editor.
Хочу еще добавить, что затык как-то связан именно с xml сериализацией, поскольку если для свойства выставить тип сериализации как
[SettingsSerializeAs(SettingsSerializeAs.Binary)] то все прекрастно работает (и в случае отсутствия атрибута [Serializable] ругается, что правильно)
p.s. Что никто не использует ApplicationBaseSettings ? Это же самый удобный и быстрый способ сохранения настроек!
Здравствуйте, altarvic, Вы писали:
A>p.s. Что никто не использует ApplicationBaseSettings ? Это же самый удобный и быстрый способ сохранения настроек!
Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.
Здравствуйте, oleksab, Вы писали:
O>Здравствуйте, altarvic, Вы писали:
A>>p.s. Что никто не использует ApplicationBaseSettings ? Это же самый удобный и быстрый способ сохранения настроек!
O> Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.
Здравствуйте, jenyavb, Вы писали:
O>> Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.
J>Как это сделать, примерчика не будет?
у меня есть примерчики, но их долго выдерать из рабочего кода
попробуй Google-ом поискать, если не получиться — буду выдирать.
Здравствуйте, oleksab, Вы писали:
O>Здравствуйте, jenyavb, Вы писали:
O>>> Самый быстрый — да. Самый удобный же imho — наследоваться от ConfigurationElement в простом случае и от ConfigurationSection — если нужно хранить внутри свои классы сложной структуры.
J>>Как это сделать, примерчика не будет?
O>у меня есть примерчики, но их долго выдерать из рабочего кода O>попробуй Google-ом поискать, если не получиться — буду выдирать.
Я вот что-то не вкуриваю: ConfigurationElement относится к ApplicationSettings (Propertyes.Settings...) или к конфигу приложения (где можно прописать ConnectionStrings, указать версию рентайма и т.п.)?
Здравствуйте, jenyavb, Вы писали:
J>Я вот что-то не вкуриваю: ConfigurationElement относится к ApplicationSettings (Propertyes.Settings...) или к конфигу приложения (где можно прописать ConnectionStrings, указать версию рентайма и т.п.)?
наверное, все-таки к конфигу приложения, потому что настройки добавляются через custom section и потом их нужно вручную вычитывать с помощью
Здравствуйте, 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 — вычитанные настройки из конфига
Здравствуйте, 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 — вычитанные настройки из конфига
Здравствуйте, 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>Да и хотелось бы сделать с новыми настрийками...
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; }
}
}
}
но это без возможности сохранения.
чтобы можно было сохранять, нужно написать код, аналогичный приведенному в предидущем сообщении.
пользоваться например так:
Здравствуйте, 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>. Должно помочь.