Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ConfigurationElementCollection包含许多不同类型的ConfigurationElements_C#_.net_App Config_System.configuration_Custom Configuration - Fatal编程技术网

C# ConfigurationElementCollection包含许多不同类型的ConfigurationElements

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 但当我启动应用程序时,我会遇到下一个可预测的

是否可以将CollectionElementCollection与许多不同类型的CollectionElements组合在一起,例如:

<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
    以在运行时替换类型。也看到