ConfigurationElementCollection with a number of ConfigurationElements of different type

邮差的信 提交于 2019-12-04 02:09:51

I looked into this as well. PolymorphicConfigurationElementCollection<T> seems deprecated. Edit: it's not, see the comment of 'abatishchev' below, i was just linking an old version.

The solution of Rest Wing was promising but unfortunately required invoking internal methods residing in another namespace. While this is possible via reflection it isn't going to receive prices for coding beauty in this case.

I digged into the source with Reflection too and came up with the following solution:

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

The override of the CollectionType is REQUIRED, even if this has been specified via the attribute in the top. When not overridden the base class' CollectionType still refers to 'AddRemoveClearMap' which isn't going to trigger the required 'CreateNewElement(string elementName)' function but it's parameterless variant 'CreateNemElement()'. For the same reason the overwritten IsElementName function should return true.

Note that I created a ElementBaseConfig which is the base class of both MyType1Config and MyType2Config in which you could define some shared attributes.

Microsoft.Practices.EnterpriseLibrary.Common.Configuration.PolymorphicConfigurationElementCollection<T> from EntLib5 do this job as a charm.

An instance of specific type (MyType1 and MyType2) needs to be created in order for child classes to resolve unknown elements or attributes by themselves.

Since the CreateNewElement method does not give any information on an element's attributes, that is not place where specific type instantiation can occur.

After some digging via Reflector, one comes to following partial call stack:

VariantCollection.MyCollection.CreateNewElement()
System.Configuration.ConfigurationElementCollection.CallCreateNewElement()
System.Configuration.ConfigurationElementCollection.OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)

The OnDeserializeUnrecognizedElement method can be overriden in MyCollection class in order to create specific type instance. Instead of using the parameterless CallCreateNewElement method, use new one that receives XmlReader:

  1. Read attribute type (ensure its existence and validity).
  2. Create new element of specified type.
  3. Call internal virtual void AssociateContext( BaseConfigurationRecord configRecord ) method of System.Configuration.ConfigurationElement on the element.
  4. Call internal void CallInit() method of System.Configuration.ConfigurationElement on the element.
  5. Return the prepared element.

BTW, if there will not be too many different collection elements, consider using something like:

<myType1Collection>
    <add Type1SpecificProp="1" />
</myType1Collection>
<myType2Collection>
    <add Type2SpecificProp="2" />
</myType2Collection>

That way you can avoid casting the items from MyCollection to specific type.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!