nestes配置元素

时间:2017-04-13 08:43:06

标签: c# web-config .net-4.5 stack-overflow app-config

我尝试使用嵌套元素进行配置。 但亲子关系是一对一的,而不是一对多的。 含义 storageProvider 只能有一个 nestedProvider

嵌套级别不受限制。

...
<store storeName="123">
    <storageProvider type="disk">        
        <nestedProvider type="share">                          
             <nestedProvider type="amazon-s3">            
             </nestedProvider>       
        </nestedProvider>
    </storageProvider>
</store>
...

问题 当我使用NestedProvider属性创建StorageProviderElement并尝试读取配置时,我在mscorlib中捕获StackOverflowException。就像.NET中有一个错误(即使用.NET 4.5)

enter image description here

我做错了什么或是预期的行为?

此时我不得不将此属性更改为集合(就像您以其他任何方式进行),但我仍然想知道为什么我不能制作嵌套的一对一元素。

代码: StoreElement

public class StoreElement : ConfigurationElement
{
    private const string storeName = "storeName";
    private const string storageProvider = "storageProvider";

    [ConfigurationProperty(storeName, IsKey = true, IsRequired = true)]
    public string StoreName
    {
        get
        {
            return (string)base[storeName];
        }
    }

    [ConfigurationProperty(storageProvider, IsRequired = true)]
    public StorageProviderElement StorageProvider
    {
        get
        {
            return (StorageProviderElement)this[storageProvider];
        }
    }
}

StorageProviderElement (这是带递归的那个)

public class StorageProviderElement : ConfigurationElement
{
    private const string type = "type";
    private const string options = "options";
    private const string nestedProvider = "nestedProvider";


    [ConfigurationProperty(type, IsRequired = true)]
    public string Type
    {
        get
        {
            return (string)base[type];
        }
    }

    [ConfigurationProperty(options, IsDefaultCollection = false, IsRequired = false)]
    public GenericConfigurationElementCollection<StorageProviderOptionElement> Options
    {
        get
        {
            return (GenericConfigurationElementCollection<StorageProviderOptionElement>) this[options];
        }
    }

    // this is what trigger stack overflow exception
    [ConfigurationProperty(nestedProvider, IsDefaultCollection = false, IsRequired = false)]
    public StorageProviderElement NestedProvider
    {
        get
        {
            return (StorageProviderElement)this[nestedProvider];
        }
    }
}

更新 Capitan显然是为了救援。 为过度教育的低调CTO教育屏幕截图:

你不能轻易看到堆叠。

enter image description here

1 个答案:

答案 0 :(得分:2)

此异常的来源是ConfigurationElement

的此方法
private static ConfigurationProperty CreateConfigurationPropertyFromAttributes(PropertyInfo propertyInformation)
{
  ConfigurationProperty configurationProperty = (ConfigurationProperty) null;
  if (Attribute.GetCustomAttribute((MemberInfo) propertyInformation, typeof (ConfigurationPropertyAttribute)) is ConfigurationPropertyAttribute)
    configurationProperty = new ConfigurationProperty(propertyInformation);
  if (configurationProperty != null && typeof (ConfigurationElement).IsAssignableFrom(configurationProperty.Type))
  {
    ConfigurationPropertyCollection result = (ConfigurationPropertyCollection) null;
    ConfigurationElement.PropertiesFromType(configurationProperty.Type, out result);
  }
  return configurationProperty;
}

它检查给定属性是否有ConfigurationProperty属性,如果是,并且属性类型继承自ConfigurationElement(您的情况) - 它会再次递归地检查该属性类型。如果属性类型与外部类类型相同 - 递归永远不会结束并导致stackoverflow异常。

所以简而言之 - 你不能这样做(当你试图获得相应的部分而不实际调用你的任何方法时会立即抛出stackoverflow):

public class StorageProviderElement : ConfigurationElement
{      
    [ConfigurationProperty("whatever")]        
    public StorageProviderElement Whatever
    {
        get;
    }
}

对我来说确实是一个错误,不确定,也许背后有一些有效的推理,但我找不到任何错误。

重现的简短示例:

class Program {
    static void Main(string[] args) {
        // throws
        ConfigurationManager.GetSection("store");                        
    }
}

public class StoreElement : ConfigurationSection
{
    [ConfigurationProperty("storageProvider")]
    public StorageProviderElement StorageProvider { get; }
}

public class StorageProviderElement : ConfigurationElement {
    [ConfigurationProperty("whatever")]
    public StorageProviderElement Whatever { get; }
}

在app.config中

<configSections>    
  <section name="store" type="ConsoleApp4.StoreElement, ConsoleApp4"/>
</configSections>
<store />