C# ConfigurationElementCollection包含许多不同类型的ConfigurationElements
是否可以将CollectionElementCollection与许多不同类型的CollectionElements组合在一起,例如:C# ConfigurationElementCollection包含许多不同类型的ConfigurationElements,c#,.net,app-config,system.configuration,custom-configuration,C#,.net,App Config,System.configuration,Custom Configuration,是否可以将CollectionElementCollection与许多不同类型的CollectionElements组合在一起,例如: <collection> <add type="MyType1, MyLib" Type1SpecificProp="1" /> <add type="MyType2, MyLib" Type2SpecificProp="2" /> </collection 但当我启动应用程序时,我会遇到下一个可预测的
<collection>
<add type="MyType1, MyLib" Type1SpecificProp="1" />
<add type="MyType2, MyLib" Type2SpecificProp="2" />
</collection
但当我启动应用程序时,我会遇到下一个可预测的错误:
无法识别的属性“Type1SpecificPro”
因为Type1SpecificProp
是在MyType1
中定义的,而不是MyElement
,特别是如果MyCollection
有下一个方法:
protected override ConfigurationElement CreateNewElement()
{
return new MyElement(); // but I want instantiate not the base class but by a type given
}
i、 e.返回基类,因此从未调用子类中的OnDeserializedAttribute()
所以问题是:如何让子类自己解析未知元素?需要创建特定类型(
MyType1
和MyType2
)的实例,以便子类自己解析未知元素或属性
由于CreateNewElement
方法不提供有关元素属性的任何信息,因此这不是可以进行特定类型实例化的地方
通过Reflector进行一些挖掘后,会出现以下部分调用堆栈:
VariantCollection.MyCollection.CreateNewElement()
System.Configuration.ConfigurationElementCollection.CallCreateNewElement()
System.Configuration.ConfigurationElementCollection.OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
可以在MyCollection
类中重写onDelement
方法,以创建特定的类型实例。不要使用无参数的CallCreateNewElement
方法,而是使用接收XmlReader
的新方法:
类型
(确保其存在和有效性)System.Configuration.ConfigurationElement
方法的internal virtual void AssociateContext(BaseConfigurationRecord configRecord)
System.Configuration.ConfigurationElement
方法的internal void CallInit()
<myType1Collection>
<add Type1SpecificProp="1" />
</myType1Collection>
<myType2Collection>
<add Type2SpecificProp="2" />
</myType2Collection>
这样可以避免将项目从
MyCollection
强制转换为特定类型。Microsoft.Practices.EnterpriseLibrary.Common.Configuration.PolymorphicConfiguration ElementCollection从EntLib5开始,将此项工作视为一种魅力。我也研究了这一点<代码>多态配置元素集合。
编辑:不是,请看下面“abatishchev”的评论,我只是链接了一个旧版本
Rest Wing的解决方案很有希望,但不幸的是需要调用驻留在另一个命名空间中的内部方法。虽然这可以通过反射实现,但在这种情况下,它不会收到编码美丽的价格
我也通过反射深入研究了源代码,并提出了以下解决方案:
class MyCollection : ConfigurationElementCollection { }
class MyElement : ConfigurationElement { }
class MyType1 : MyElement { }
class MyType2 : MyElement { }
...
etc
[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的基类,您可以在其中定义一些共享属性。您已经链接了。3.1,而不是过时。你是对的,改变了我的答案以反映这一点。感谢您的注意。我知道这个答案不久前就发布了,但是如果您要将其标记为已接受的答案,您可以更详细地介绍一下吗?@goric:您需要继承它并重写
RetrieveConfiguration ElementType
以在运行时替换类型。也看到