C# .Net自定义configSection中的条目是否共享属性名称?

C# .Net自定义configSection中的条目是否共享属性名称?,c#,.net,app-config,C#,.net,App Config,我有一些.NETC代码,我承认是我写的——很多月前,它并没有像预期的那样工作,而现在,在它编写5年后,我似乎发现了一个我无法解释的错误 基本上,我有一个应用程序配置文件,带有一个自定义配置部分,它描述了许多实体。看起来,当它工作时,如果我寻找一个不存在的属性,我会得到不同的结果,如果该属性真的不存在于任何地方,与特定实体/元素的属性不存在相比 如果该属性不存在于任何实体上,则对ConfigurationElement.Properties.ContainspropertyName的调用将返回fa

我有一些.NETC代码,我承认是我写的——很多月前,它并没有像预期的那样工作,而现在,在它编写5年后,我似乎发现了一个我无法解释的错误

基本上,我有一个应用程序配置文件,带有一个自定义配置部分,它描述了许多实体。看起来,当它工作时,如果我寻找一个不存在的属性,我会得到不同的结果,如果该属性真的不存在于任何地方,与特定实体/元素的属性不存在相比

如果该属性不存在于任何实体上,则对ConfigurationElement.Properties.ContainspropertyName的调用将返回false,但如果该属性至少存在于一个实体上,则无论该属性是否存在于当前ConfigurationElement上,都将返回true

有人能解释为什么这种行为是这样的,无论是通过设计,还是我的一些编码错误

编辑:配置元素thing1似乎有三个属性name,setting1,setting2,即使在配置文件中只显示前两个。我猜底层代码假设所有元素都可以具有相同的属性集

program.cs

App.config


嗯。。。这里的一个选项似乎是覆盖自定义ConfigurationElement上的反序列化Element方法。此时,Xml元素在XmlReader中,我可以使用它来获取当前属性的名称。如果保存这些名称,在GetProperty方法中,如果反序列化时命名属性不存在,则可以返回null

public partial class MyConfigurationElement : ConfigurationElement
{
    private List<String> _propertyNames = new List<String>();

    :

    public String GetProperty(String propertyName)
    {
        if (_propertyNames.Contains(propertyName))
            return base[propertyName].ToString();
        else
            return null;
    }

    public void SetProperty(String propertyName, String value)
    {
        if (base.Properties.Contains(propertyName))
        {
            base.SetPropertyValue(base.Properties[propertyName], value, false);
        }
        else
        {
            ConfigurationProperty cp = new ConfigurationProperty(propertyName, typeof(String));
            base.Properties.Add(cp);
            base.SetPropertyValue(cp, value, false);
        }

        if (!_propertyNames.Contains(propertyName)) _propertyNames.Add(propertyName);
    }

    :

    protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey)
    {
        base.DeserializeElement(reader, serializeCollectionKey);

        if (reader.MoveToFirstAttribute() == true)
        {
            do
            {
                _propertyNames.Add(reader.Name);
            } while (reader.MoveToNextAttribute());

            reader.MoveToElement();
        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="thingSettings" type="Testing.ThingsConfigurationSection, MyConfigurationElement, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </configSections>

  <thingSettings>
    <things>
      <add name="Thing 1"
           Setting1="true"
         />

      <add name="Thing 2"
           Setting1="false"
           Setting2="true"
         />
    </things>
  </thingSettings>

</configuration>
public partial class MyConfigurationElement : ConfigurationElement
{
    private List<String> _propertyNames = new List<String>();

    :

    public String GetProperty(String propertyName)
    {
        if (_propertyNames.Contains(propertyName))
            return base[propertyName].ToString();
        else
            return null;
    }

    public void SetProperty(String propertyName, String value)
    {
        if (base.Properties.Contains(propertyName))
        {
            base.SetPropertyValue(base.Properties[propertyName], value, false);
        }
        else
        {
            ConfigurationProperty cp = new ConfigurationProperty(propertyName, typeof(String));
            base.Properties.Add(cp);
            base.SetPropertyValue(cp, value, false);
        }

        if (!_propertyNames.Contains(propertyName)) _propertyNames.Add(propertyName);
    }

    :

    protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey)
    {
        base.DeserializeElement(reader, serializeCollectionKey);

        if (reader.MoveToFirstAttribute() == true)
        {
            do
            {
                _propertyNames.Add(reader.Name);
            } while (reader.MoveToNextAttribute());

            reader.MoveToElement();
        }
    }
}