2012-05-05 3 views
1

Я хотел бы сохранить некоторые данные между сеансами приложений и решил использовать .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; 
    } 
} 

Заранее спасибо!

ответ

3

Посмотрите на «Configuration Section Designer», это отличный «Visual Studio надстройка, которая позволяет графически разрабатывать разделы .NET конфигурации и автоматически генерирует все необходимые коды и определение схемы (XSD) для них ».

Создайте конфигурационный раздел с помощью этого инструмента, [я думаю, вам понравится :)].

+0

Спасибо ... Кажется, что это хорошо. Попытаюсь. – Regfor

+0

Спасибо, мне нужно работать с классами, созданными конструктором раздела конфигурации. Я хочу посмотреть, какая разница между моим кодом и сгенерированным кодом - найти проблему прямо сейчас. – Michael

+0

ОК, я нашел основные отличия между кодом, сгенерированным конструктором разделов конфигурации и моим кодом, и, кроме некоторых различий, которые кажутся несущественными, я обнаружил, что у меня были некоторые атрибуты в неправильном месте. Спасибо, решено! – Michael