【问题标题】:StackOverflowException for nestes configuration elements嵌套配置元素的 StackOverflowException
【发布时间】:2023-04-01 02:10:01
【问题描述】:

我正在尝试使用嵌套元素进行配置。 但是父子关系是一对一的,而不是一对多的。 意思是 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)

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

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

代码: 存储元素

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

更新: 显示 StackOverflowException 难以调试的原因的屏幕截图。

【问题讨论】:

  • 你自己造成了StackOverflowException。查看调试器中的调用堆栈。
  • @PatrickHofman 不,我不是,看屏幕。
  • 是的,你是...调用堆栈是什么?
  • 可以添加调用栈吗?您是否调试过代码以查看代码是否按预期运行?
  • 能否请您更具体/有帮助。什么可能在这里触发 StackOverflowException?我使用 C#,因为它是发明的并且可以区分异常:)

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


【解决方案1】:

这个异常的来源是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 />

【讨论】:

  • 旁注:要查看StackOverflowException 的堆栈跟踪,您可以在附加调试器的情况下运行,然后当它被抛出时打开“调用堆栈”窗口(调试> Windows > 调用堆栈)。在这种情况下,问题可以通过您提供的代码重现,因此不是必需的(但仍然很好)。
  • 对于示例是的,但它不适用于 mscorlib 异常,或者我错过了什么?
  • 不确定“sample”和“mscorlib”异常是什么意思。在您的特定情况下,附加调试器后,您将在我提到的那个窗口中看到当前调用堆栈(行如“mscorlib.dll!System.ModuleHandle.ResolveMethodHandleInternalCore(...)”。)即使StackTrace 异常本身的属性将为空。
  • 我意识到框架源代码的调试被禁用了。现在我可以看到所有细节了。
猜你喜欢
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多