2017-04-13 22 views
-1

我試圖用嵌套元素進行配置。 但親子關係是一對一,而不是一對多。 含義storageProvider可能只有一個nestedProvider針對nestes配置元素的StackOverflowException

嵌套級別不受限制。

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

問題 當我創建StorageProviderElement與NestedProvider財產,並嘗試讀取配置我趕上StackOverflowException在mscorlib中。好像有一個錯誤在.NET(使用.NET 4.5 IM)

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

UPDATE: 匹明顯的救援。 教育屏幕截圖超過受教育的downvoting首席技術官:

你不能看到堆疊EASEYLLY。

enter image description here

+0

你正在自己造成'StackOverflowException'。在調試器中查看調用堆棧。 –

+0

@PatrickHofman沒有我不是,看屏幕。 – ADOConnection

+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異常。

因此,在短期 - 你不能做到這一點(將計算器立即拋出,當您嘗試獲取相應的部分,而無需實際調用你的任何方法):

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

在應用程序。config

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

謝謝指出。 – ADOConnection

+0

注意:要查看StackOverflowException的堆棧跟蹤,您可以使用附加的調試器運行,然後當它被拋出時打開「調用堆棧」窗口(調試> Windows>調用堆棧)。在這種情況下,問題可以通過您提供的代碼進行再現,所以它不是必需的(但仍然很好)。 – Evk

+0

是示例是,但它不適用於mscorlib異常,或者我錯過了某些東西? – ADOConnection