ConfigurationElementCollection具有许多不同类型的ConfigurationElements
是否可以使CollectionElementCollection具有许多不同类型的CollectionElements,例如:
</collection
我有这样的解决方案所需的所有类:
class MyCollection : ConfigurationElementCollection { } class MyElement : ConfigurationElement { } class MyType1 : MyElement { } class MyType2 : MyElement { } ... etc
但当我启动我的应用程序时,我得到下一个可预测的错误:
无法识别的属性’Type1SpecificProp’。
因为Type1SpecificProp
是在MyType1
而不是MyElement
定义的,特别是如果MyCollection
具有下一个方法:
protected override ConfigurationElement CreateNewElement() { return new MyElement(); // but I want instantiate not the base class but by a type given }
即返回基类,因此从未调用子类中的OnDeserializeUnrecognizedAttribute()
。
所以问题是:如何让孩子们的class级通过他们自己解决未知元素?
我也调查了这个。 PolymorphicConfigurationElementCollection
似乎已弃用 。 编辑:不是,请参阅下面的’abatishchev’评论,我只是链接旧版本。
Rest Wing的解决方案很有希望,但不幸的是需要调用驻留在另一个命名空间中的内部方法。 虽然这可以通过reflection来实现,但在这种情况下它不会收到编码美的价格。
我也使用Reflection挖掘了源代码并提出了以下解决方案:
[ConfigurationCollection(typeof(ElementBaseConfig), CollectionType=ConfigurationElementCollectionType.BasicMap)] public class MyTypesConfigCollection : ConfigurationElementCollection { protected override ConfigurationElement CreateNewElement() { // Not used but function must be defined return null; } protected override object GetElementKey(ConfigurationElement element) { return element; } protected override ConfigurationElement CreateNewElement(string elementName) { switch (elementName) { case "mytype1": return new MyType1Config(); case "mytype2": return new MyType2Config(); default: throw new ConfigurationErrorsException( string.Format("Unrecognized element '{0}'.", elementName)); } } protected override bool IsElementName(string elementName) { // Required to be true return true; } public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } }
CollectionType的覆盖是必需的,即使已通过顶部的属性指定了它。 当没有重写时,基类’CollectionType仍然引用’AddRemoveClearMap’,它不会触发所需的’CreateNewElement(string elementName)’函数,但它是无参数变量’CreateNemElement()’。 出于同样的原因,覆盖的IsElementName函数应该返回true。
请注意,我创建了一个ElementBaseConfig,它是MyType1Config和MyType2Config的基类,您可以在其中定义一些共享属性。
来自EntLib5的Microsoft.Practices.EnterpriseLibrary.Common.Configuration.PolymorphicConfigurationElementCollection
将此作为魅力。
需要创建特定类型的实例( MyType1
和MyType2
),以便子类自己解析未知元素或属性。
由于CreateNewElement
方法不提供有关元素属性的任何信息,因此不是特定类型实例化可能发生的位置。
在通过Reflector进行一些挖掘后,可以看到以下部分调用堆栈:
VariantCollection.MyCollection.CreateNewElement() System.Configuration.ConfigurationElementCollection.CallCreateNewElement() System.Configuration.ConfigurationElementCollection.OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
OnDeserializeUnrecognizedElement
方法可以在MyCollection
类中重写,以便创建特定的类型实例。 不使用无参数的CallCreateNewElement
方法,而是使用接收XmlReader
新方法:
- 读属性
type
(确保其存在和有效性)。 - 创建指定类型的新元素。
- 在元素上调用
System.Configuration.ConfigurationElement
internal virtual void AssociateContext( BaseConfigurationRecord configRecord )
方法。 - 在元素上调用
System.Configuration.ConfigurationElement
internal void CallInit()
方法。 - 返回准备好的元素。
顺便说一句,如果不会有太多不同的集合元素,请考虑使用以下内容:
这样您就可以避免将项目从MyCollection
为特定类型。