Я хотел бы сохранить некоторые данные между сеансами приложений и решил использовать .NET Configuration API (System.Configuration
), что оказалось намного сложнее, чем я ожидал.Секция пользовательской настройки сохранена без данных
Я создал пользовательский раздел конфигурации, так:
UserMailSourcesSection
public class UserMailSourcesSection : ConfigurationSection
{
[ConfigurationProperty("User", IsRequired = true)]
public string User { get; set; }
[ConfigurationProperty("UserMailSources", IsDefaultCollection = false)]
[ConfigurationCollection(typeof(MailSourceElemet))]
public MailSourceElemetCollection MailSources
{
get
{
return (MailSourceElemetCollection)this["UserMailSources"];
}
set
{
this["UserMailSources"] = value;
}
}
public UserMailSourcesSection()
{
this.User = String.Empty;
}
}
(Остальная часть соответствующего кода в конце вопроса)
теперь Фактическая проблема заключалась в том, что я получал исключения (не очень описательные, заметьте) со стороны моего кода, который сохранил этот раздел после того, как он был настроен со всеми значениями, которые я хотел сохранить. Я проследил его до MailSourceElementCollection.Add
, который вызывается с параметром, имеющим несколько нулевых значений. Этот параметр передавался из кода Microsoft. Я понял, что он должен создавать новый экземпляр параметра с конструктором без параметров по умолчанию. Хотя я решил написать конструктор без параметров, который заменил бы нулевые значения каким-либо значением по умолчанию (в частности String.Empty
), и это, казалось, сработало. Код побежал, метод сохранения не кидал, но возникла новая проблема - никакие данные не были фактически сохранены, хотя я явно установить все в главном методе:
PublisherElemet publisher = new PublisherElemet();
publisher.Publisher = "test";
PublisherElementCollection publishers = new PublisherElementCollection();
publishers.Add(publisher);
MailSourceElemet mailSource = new MailSourceElemet();
mailSource.HostName = "test";
mailSource.Port = 0;
mailSource.Username = "test";
mailSource.Password = "test";
mailSource.Publishers = publishers;
MailSourceElemetCollection mailSources = new MailSourceElemetCollection();
mailSources.Add(mailSource);
UserMailSourcesSection userMailSources = new UserMailSourcesSection();
userMailSources.User = Environment.UserName;
userMailSources.MailSources = mailSources;
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Add("MailSources", userMailSources);
config.Save(ConfigurationSaveMode.Modified);
После этого ожидается выход был:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="MailSources" type="Email_To_Rss_V2.Classes.UserMailSourcesSection, Email-To-Rss-V2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<MailSources User="User">
<UserMailSources>
<add HostName="test" Port="0" Username="test" Password="test">
<Publishers>
<add Publihser="test" />
</Publishers>
</add>
</UserMailSources>
</MailSources>
в то время как фактический выход был:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="MailSources" type="Email_To_Rss_V2.Classes.UserMailSourcesSection, Email-To-Rss-V2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<MailSources User="">
<UserMailSources>
<add HostName="" Port="0" Username="" Password="">
<Publishers>
<add Publihser="" />
</Publishers>
</add>
</UserMailSources>
</MailSources>
действительно странно было то, что в отладчике данных было показано, что там, он просто не кажется, вывод в файл.
Вот остальная часть соответствующего кода:
MailSourceElementCollection
public class MailSourceElemetCollection : ConfigurationElementCollection
{
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.AddRemoveClearMap;
}
}
public MailSourceElemet this[int index]
{
get
{
return (MailSourceElemet)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(0, value);
}
}
protected override object GetElementKey(ConfigurationElement element)
{
if (((MailSourceElemet)element).Username == null)
{
Console.WriteLine("null");
}
return ((MailSourceElemet)element).Username;
}
protected override ConfigurationElement CreateNewElement()
{
return new MailSourceElemet();
}
public void Add(MailSourceElemet mailSource)
{
BaseAdd(mailSource);
}
public void Clear()
{
this.BaseClear();
}
public void Remove(MailSourceElemet element)
{
BaseRemove(element.Username);
}
public void Remove(string name)
{
BaseRemove(name);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
}
MailSourceElement
public class MailSourceElemet : ConfigurationElement
{
[ConfigurationProperty("HostName", IsRequired = true)]
public string HostName { get; set; }
[ConfigurationProperty("Port", IsRequired = true)]
public int Port { get; set; }
[ConfigurationProperty("Username", IsRequired = true)]
public string Username { get; set; }
[ConfigurationProperty("Password", IsRequired = true)]
public string Password { get; set; }
[ConfigurationProperty("Publishers", IsDefaultCollection = false)]
[ConfigurationCollection(typeof(PublisherElemet))]
public PublisherElementCollection Publishers
{
get
{
return (PublisherElementCollection)this["Publishers"];
}
set
{
this["Publishers"] = value;
}
}
public MailSourceElemet()
{
this.HostName = String.Empty;
this.Port = 0;
this.Username = String.Empty;
this.Password = String.Empty;
}
}
PublisherElementCollection
public class PublisherElementCollection : ConfigurationElementCollection
{
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.AddRemoveClearMap;
}
}
public PublisherElemet this[int index]
{
get
{
return (PublisherElemet)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(0, (PublisherElemet)value);
}
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((PublisherElemet)element).Publisher;
}
protected override ConfigurationElement CreateNewElement()
{
return new PublisherElemet();
}
public void Add(PublisherElemet publisher)
{
BaseAdd(publisher);
}
public void Clear()
{
this.BaseClear();
}
public void Remove(PublisherElemet publisher)
{
BaseRemove(publisher.Publisher);
}
public void Remove(string name)
{
BaseRemove(name);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
}
PublisherElement
public class PublisherElemet : ConfigurationElement
{
[ConfigurationProperty("Publihser", IsRequired = true)]
public string Publisher { get; set; }
public PublisherElemet()
{
Publisher = String.Empty;
}
}
Заранее спасибо!
Спасибо ... Кажется, что это хорошо. Попытаюсь. – Regfor
Спасибо, мне нужно работать с классами, созданными конструктором раздела конфигурации. Я хочу посмотреть, какая разница между моим кодом и сгенерированным кодом - найти проблему прямо сейчас. – Michael
ОК, я нашел основные отличия между кодом, сгенерированным конструктором разделов конфигурации и моим кодом, и, кроме некоторых различий, которые кажутся несущественными, я обнаружил, что у меня были некоторые атрибуты в неправильном месте. Спасибо, решено! – Michael