嵌套配置元素的 StackOverflowException
StackOverflowException for nestes configuration elements
我正在尝试使用嵌套元素进行配置。
但是父子关系是一对一的,而不是一对多的。
意思是 storageProvider 只能有一个 nestedProvider.
嵌套层数不限
...
<store storeName="123">
<storageProvider type="disk">
<nestedProvider type="share">
<nestedProvider type="amazon-s3">
</nestedProvider>
</nestedProvider>
</storageProvider>
</store>
...
问题
当我使用 NestedProvider 属性 创建 StorageProviderElement 并尝试读取配置时,我在 mscorlib 中捕获了 WhosebugException。好像 .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];
}
}
}
更新:
显示 WhosebugException 为何难以调试的屏幕截图。
这个异常的来源是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
(你的情况) - 它递归地检查 属性 再次输入。如果 属性 类型与外部 class 类型相同 - 递归永远不会结束并导致 Whosebug 异常。
所以简而言之 - 你不能这样做(当你试图获取相应的部分时会立即抛出 Whosebug,而不实际调用你的任何方法):
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 />
我正在尝试使用嵌套元素进行配置。 但是父子关系是一对一的,而不是一对多的。 意思是 storageProvider 只能有一个 nestedProvider.
嵌套层数不限
...
<store storeName="123">
<storageProvider type="disk">
<nestedProvider type="share">
<nestedProvider type="amazon-s3">
</nestedProvider>
</nestedProvider>
</storageProvider>
</store>
...
问题 当我使用 NestedProvider 属性 创建 StorageProviderElement 并尝试读取配置时,我在 mscorlib 中捕获了 WhosebugException。好像 .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];
}
}
}
更新: 显示 WhosebugException 为何难以调试的屏幕截图。
这个异常的来源是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
(你的情况) - 它递归地检查 属性 再次输入。如果 属性 类型与外部 class 类型相同 - 递归永远不会结束并导致 Whosebug 异常。
所以简而言之 - 你不能这样做(当你试图获取相应的部分时会立即抛出 Whosebug,而不实际调用你的任何方法):
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 />