C# - ConfigurationSection isRequired属性

时间:2010-11-03 21:07:46

标签: c# configuration config

我遇到了这个奇怪的问题...在我的代码中,我是否将IsRequired的值设置为false或true然后它保持为false。但是如果我输入DefaultValue它会起作用吗?

非工作代码是:

public class FtpSettingsSection : ConfigurationSection
{
    [ConfigurationProperty("host", IsRequired = true)]
    public HostElement Host
    {
        get { return (HostElement)this["host"]; }
        set { this["host"] = value; }
    }

}

public class HostElement : ConfigurationElement
{
    [ConfigurationProperty("URL", IsRequired = true)]
    public string URL
    {
        get { return (string)this["URL"]; }
        set { this["URL"] = value; }
    }
}

,工作代码是:

public class FtpSettingsSection : ConfigurationSection
{
    [ConfigurationProperty("host", DefaultValue = "", IsRequired = true)]
    public HostElement Host
    {
        get { return (HostElement)this["host"]; }
        set { this["host"] = value; }
    }

}

public class HostElement : ConfigurationElement
{
    [ConfigurationProperty("URL", DefaultValue = "", IsRequired = true)]
    public string URL
    {
        get { return (string)this["URL"]; }
        set { this["URL"] = value; }
    }
}

为什么我需要将DefaultValue设置为“”?

4 个答案:

答案 0 :(得分:6)

我遇到了同样的问题,并在http://msdn.microsoft.com/en-us/library/system.configuration.configurationpropertyattribute%28v=vs.90%29.aspx#1找到了解决方案。对ConfigurationPropertyAttribute的评论并不完全正确,但它解释了问题的基础:

  

IsRequired ConfigurationPropertyAttribute成员在应用于子对象(从ConfigurationElement派生)时不起作用。当子系统反映父节/元素的属性以确定定义了哪些配置属性时,它将为每个子元素创建一个新的实例(适当类型)并将其存储在父元素的值列表中。稍后,当它验证是否已指定所有必需属性时,它无法区分默认初始化子元素和配置文件中显式包含的元素。

     

最理想的解决方法是通过ConfigurationProperty类以编程方式声明所需的元素。这需要比声明方法更多的工作。另一种选择......

据我所知,替代方案不正确。

可以在ConfigurationProperty页面上找到编程模型的示例。我已经设法通过在我的自定义元素的构造函数中声明我需要的属性并将其他所有内容保持不变来为自己解决问题。

我怀疑你添加DefaultValue时实际上并没有工作,而是因为其他原因而抛出异常。您必须深入到InnerException链的末尾才能找到ConfigurationErrorsException。缺少必需属性时的正确消息是“找不到必需属性'主机'。(C:\ path \ to \ yourproject \ bin \ Debug \ yourproject.vshost.exe.Config line ##)”

当您提供空字符串默认值时,配置子系统将尝试将该字符串解析为HostElement并失败。生成的ConfigurationErrorsException具有消息“无法解析属性'host'的默认值。错误是:对象引用未设置为对象的实例。(C:\ path \ to \ yourproject \ bin \ Debug \ yourproject.vshost.exe.Config line ##)“

答案 1 :(得分:4)

挖掘一个死线程。 但我偶然发现了一个解决方法。

在自定义部分构造函数中,引用自定义元素的ElementInformation。通过这样做,您的自定义部分的另一个实例将在元素的上下文中创建。由于某种原因,我完全不了解,IsRequired属性很荣幸。

public class FtpSettingsSection : ConfigurationSection
{
    public FtpSettingsSection() 
    {
        // force it to double load.
        if (this.Host.ElementInformation.IsPresent) ;
    }

    [ConfigurationProperty("host", IsRequired = true)]
    public HostElement Host
    {
        get { return (HostElement)this["host"]; }
        set { this["host"] = value; }
    }
}

答案 2 :(得分:3)

对于necroposting很抱歉,但是这个问题也让我感到困惑,但是更加特殊,我的解决方案也适用于提出的问题。

我实现了重新加载配置而不重新启动进程。 当流程开始时, IsRequired 属性被“忽略”, ConfigurationElement 以默认值静默初始化。但是当重新加载配置时, IsRequired 属于尊重!所以我在进程启动时硬编码重新加载配置,它解决了丢失异常的问题!

伪代码:

config = (SampleConfiguration)ConfigurationManager.GetSection(ConfigSectionName);
// <-- no exception thrown for missing required properties

ConfigurationManager.RefreshSection(ConfigSectionName);

config = (SampleConfiguration)ConfigurationManager.GetSection(ConfigSectionName);
// <-- exception thrown!

答案 3 :(得分:0)

我假设你没有在你的配置中序列化URL属性的值。因此,在加载配置时,ConfigurationManager会检查属性以查看是否需要属性值,然后如果找不到值则抛出异常。如果设置了默认值,则在配置中找不到该值时使用该值。