2017-04-13 2 views
-1

Je tente d'effectuer une configuration avec des éléments imbriqués. mais la relation parent-enfant est un-à-un, pas un-à-plusieurs. Signification storageProvider peut avoir un seul nestedProvider.StackOverflowException pour les éléments de configuration nestes

Le niveau d'imbrication n'est pas limité.

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

Question Lorsque je crée StorageProviderElement la propriété NestedProvider et essayer de lire la configuration que j'attraper StackOverflowException dans mscorlib. Comme il y a un bogue dans .NET (im en utilisant .NET 4.5)

enter image description here

que je fais quelque chose de mal ou ce comportement est normal?

À ce stade, j'ai dû changer cette propriété à une collection (comme vous le faites de toute autre manière) mais je me demande encore pourquoi je ne peux pas faire des éléments imbriqués un-à-un.

code: 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 (c'est celui avec récursivité)

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

MISE À JOUR: Capitan évidente à la rescousse. Capture d'écran éducative pour CTOs downvoting éduqués:

VOUS NE POUVEZ PAS VOIR STACK EASEYLLY.

enter image description here

+0

Vous provoquez le 'StackOverflowException' vous-même. Voir la pile des appels dans le débogueur. –

+0

@PatrickHofman non im non, voir écran. – ADOConnection

+0

Oui, vous êtes ... Quelle est la pile d'appels? –

Répondre

2

La source de cette exception est cette méthode de 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; 
} 

Il vérifie s'il y a ConfigurationProperty attribut donné la propriété et si oui et le type de propriété hérite de ConfigurationElement (votre cas) - il inspecte de façon récursive ce type de propriété à nouveau. Si le type de propriété est le même que le type de classe externe, la récursivité ne se termine jamais et entraîne une exception stackoverflow.

Donc en bref - vous ne pouvez pas le faire (jetteront stackoverflow immédiatement lorsque vous essayez d'obtenir la section correspondante, sans appeler effectivement l'une de vos méthodes):

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

On dirait un bug pour moi en effet, pas Bien sûr, peut-être y a-t-il un raisonnement valable, mais je n'en trouve pas.

court exemple à reproduire:

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

En application.config

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

merci de souligner. – ADOConnection

+0

Note latérale: pour voir la trace de pile de 'StackOverflowException', vous pouvez exécuter le débogueur attaché, puis quand il est ouvert, ouvrez la fenêtre" call stack "(Débogage> Windows> Call Stack). Dans ce cas, le problème est reproductible avec un code que vous avez fourni, donc ce n'est pas obligatoire (mais c'est toujours bien d'avoir). – Evk

+0

pour l'échantillon oui, mais son ne fonctionne pas pour l'exception mscorlib, ou quelque chose me manque? – ADOConnection