【问题标题】:Custom Configuration Section saved with no Data保存的自定义配置部分没有数据
【发布时间】:2012-05-06 02:20:13
【问题描述】:

我想在应用程序会话之间保留一些数据,并决定使用 .NET 配置 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)替换空值,这似乎有效。代码运行了,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);

在此之后预期的输出是:

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

提前致谢!

【问题讨论】:

    标签: c# .net configuration app-config


    【解决方案1】:

    看看'Configuration Section Designer',这是一个很好的 'Visual Studio 插件,允许您以图形方式设计 .NET 配置部分并自动为它们生成所有必需的代码和架构定义 (XSD)。

    使用这个工具设计你的配置部分,[我想你会喜欢它的 :)]。

    【讨论】:

    • 谢谢,我已经让它与配置部分设计器生成的类一起工作。我正在查看我的代码和生成的代码之间的区别是什么,以便立即发现问题。
    • 好的,我发现了配置部分设计器生成的代码和我的代码之间的主要区别,除了一些看起来无关紧要的区别之外,我发现我在错误的地方有一些属性。谢谢,解决了!
    • 很高兴知道它对您有用。几天前,我必须设计一个大型配置,这对我帮助很大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 2010-10-25
    • 2010-11-12
    • 2013-09-17
    • 2011-07-04
    相关资源
    最近更新 更多