【问题标题】:C# - ConfigurationSection isRequired attributeC# - ConfigurationSection isRequired 属性
【发布时间】:2011-05-04 18:00:42
【问题描述】:

我遇到了这个奇怪的问题...在我的代码中,无论我将 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 设置为“”?

【问题讨论】:

    标签: c# configuration config


    【解决方案1】:

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

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

      挖掘死线程。 但我不小心找到了解决方法。

      在您的自定义部分构造函数中,引用自定义元素的 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; }
          }
      }
      

      【讨论】:

        【解决方案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!
        

        【讨论】:

          【解决方案4】:

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

          【讨论】:

          • 第一个代码示例即使配置文件中没有定义主机属性也会抛出任何异常?
          • 第一个例子会抛出异常,带有默认属性的第二个不会。
          • 实际上我对此进行了测试,第一个示例没有引发异常。在测试控制台应用程序中,IsRequired 似乎被忽略了。如果是 IsRequired,则不应设置默认值,因为它实际上不是必需的。如果您将其标记为 IsRequired=true,那么如果您不提供默认值但它没有提供,它应该抛出异常。我在 .Net 4 中测试过。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多