Вопрос

Возможно ли иметь CollectionElementCollection с несколькими различными по типу CollectionElements, например:

<collection>
    <add type="MyType1, MyLib" Type1SpecificProp="1" />
    <add type="MyType2, MyLib" Type2SpecificProp="2" />
</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() в дочерних классах они никогда не вызывались.

Итак, вопрос заключается в следующем:как разрешить дочерним классам самостоятельно разрешать неизвестные элементы?

Это было полезно?

Решение 2

Microsoft.Practices.EnterpriseLibrary.Common.Configuration.PolymorphicConfigurationElementCollection<T> из EntLib5 отлично справляется с этой задачей.

Другие советы

Я тоже занимался этим. PolymorphicConfigurationElementCollection<T> кажется устаревшим . Изменить: это не так, см. Комментарий abatishchev ниже, я просто связывал старую версию.

Решение Rest Wing было многообещающим, но, к сожалению, требовало вызова внутренних методов, находящихся в другом пространстве имен. Хотя это возможно с помощью отражения, в этом случае плата за кодирование красоты не взимается.

Я тоже покопался в источнике с помощью Reflection и нашел следующее решение:

родовое слово

ТРЕБУЕТСЯ переопределение CollectionType, даже если это было указано через атрибут вверху. Если базовый класс не переопределен, CollectionType по-прежнему ссылается на AddRemoveClearMap, который не будет запускать требуемую функцию CreateNewElement (string elementName), а это вариант без параметров CreateNemElement (). По той же причине перезаписанная функция IsElementName должна возвращать значение true.

Обратите внимание, что я создал ElementBaseConfig, который является базовым классом как MyType1Config, так и MyType2Config, в котором вы можете определять некоторые общие атрибуты.

Экземпляр определенного типа (MyType1 и MyType2) необходимо создать для того, чтобы дочерние классы могли сами разрешать неизвестные элементы или атрибуты.

С тех пор, как CreateNewElement метод не предоставляет никакой информации об атрибутах элемента, то есть это не то место, где может произойти создание экземпляра определенного типа.

После некоторого копания с помощью Reflector можно прийти к следующему частичному стеку вызовов:

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

Тот Самый OnDeserializeUnrecognizedElement метод может быть переопределен в MyCollection класс для того, чтобы создать экземпляр определенного типа.Вместо использования параметра без параметров CallCreateNewElement метод, используйте новый, который получает XmlReader:

  1. Атрибут чтения type (обеспечить его существование и действительность).
  2. Создайте новый элемент указанного типа.
  3. Звонить internal virtual void AssociateContext( BaseConfigurationRecord configRecord ) способ получения System.Configuration.ConfigurationElement об элементе.
  4. Звонить internal void CallInit() способ получения System.Configuration.ConfigurationElement об элементе.
  5. Верните подготовленный элемент.

Кстати, если не будет слишком много разных элементов коллекции, рассмотрите возможность использования чего-то вроде:

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

Таким образом, вы можете избежать приведения элементов из MyCollection к определенному типу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top