简体   繁体   English

保存的自定义配置部分没有数据

[英]Custom Configuration Section saved with no Data

I've wanted to persist some data between application sessions and decided to use the .NET Configuration API ( System.Configuration namespace) which has proven to be far more difficult than I expected. 我想在应用程序会话之间保留一些数据,并决定使用.NET配置API( System.Configuration命名空间),这已被证明比我预期的要困难得多。

I've created a custom configuration section as so: 我已经创建了一个自定义配置部分:

UserMailSourcesSection 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;
    }
}

(The rest of the relevant code is at the end of the question) (其余相关代码在问题的最后)

Now the actual problem was that I was getting exceptions (not very descriptive ones, mind you) from the part of my code that saved this section after it's been configured with all the values I wanted to persist. 现在实际的问题是,在我配置了我想要保留的所有值之后,我从我的代码中保存了这部分的部分得到了异常(不是非常具有描述性的,请注意)。 I traced it down to the MailSourceElementCollection.Add being called with a parameter that had some null values. 我将其追溯到使用具有一些空值的参数调用的MailSourceElementCollection.Add That parameter was being passed from Microsofts code. 该参数是从微软代码传递的。 I deduced that it must be creating a new instance of the parameter with the default parameter-less constructor. 我推断它必须使用默认的无参数构造函数创建参数的新实例。 I though the solution would be to explicitly write a parameter-less constructor that would replace the null values with some kind of defaults (specifically String.Empty ) and that seemed to work. 我虽然解决方案是显式编写一个无参数的构造函数,用一些默认值(特别是String.Empty )替换null值,这似乎有效。 The code ran, the save method didn't throw but there was a new problem - no data was actually being saved even though I explicitly set everything in the Main method: 代码运行,save方法没有抛出,但是出现了一个新问题 - 即使我在Main方法中明确设置了所有内容,也没有实际保存数据:

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);

After this the expected output was: 在此之后,预期的输出是:

<?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>

While the actual output was: 而实际输出是:

<?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>

The really weird thing was that in the debugger the data was shown to be there, it just didn't seem to output to file. 真正奇怪的是,在调试器中数据显示在那里,它似乎没有输出到文件。

Here's the rest of the relevant code: 以下是相关代码的其余部分:

MailSourceElementCollection 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 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 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 PublisherElement

public class PublisherElemet : ConfigurationElement
{
    [ConfigurationProperty("Publihser", IsRequired = true)]
    public string Publisher { get; set; }

    public PublisherElemet()
    {
        Publisher = String.Empty;
    }
}

Thanks in advance! 提前致谢!

Have a look on the ' Configuration Section Designer ', this is an excellent 'Visual Studio add-in that allows you to graphically design .NET Configuration Sections and automatically generates all the required code and a schema definition (XSD) for them'. 查看“ 配置部分设计器 ”,这是一个出色的'Visual Studio插件,允许您以图形方式设计.NET配置部分,并自动生成所有必需的代码和模式定义(XSD)。

Design you configuration section using this tool, [I think you will love it :)]. 使用这个工具设计你的配置部分,[我想你会喜欢它:)]。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM