XmlInclude для (де) сериализации унаследованных типов в отдельных сборках - PullRequest
2 голосов
/ 25 июня 2010

У меня есть такой сценарий:

namespace MyApp.Animals
{
  public class Dog : MyApp.Categories.Canine
  ...

Так что я пытаюсь сериализовать / десериализовать класс собаки. К сожалению, я не могу использовать атрибут [XmlInclude], потому что, добавляя его в родительский класс (MyApp.Categories.Canine), мне нужно добавить ссылку на сборку, в которой существует родительский класс (MyApp.Animals) .. однако дочерний класс уже ссылается на родительский класс из-за наследования ... поэтому у нас есть циклическая ссылка.

Есть ли лучший способ достижения этой цели? Я могу обойти это, вручную сериализовав / десериализовав свойства, существующие в родительском классе, и просто выполняя сериализацию для дочернего, но это не очень элегантно.

Надеясь на лучшие советы ...

ОБНОВЛЕНИЕ: Добавление к примеру в ответ на комментарий Джона ниже ...

У меня нет полного примера кода (код, с которым я работаю, массивный и сложный), но проблема в том, что некоторые из свойств, которые должны де / сериализироваться в / из xml, содержатся в родительском классе, который находится в другой сборке с дочерним классом.

Добавление атрибутов XmlElement к родительскому классу не работает, поскольку мы фактически выполняем де / сериализацию для дочернего класса, поэтому он не повторяется до родительского класса. И мы не можем сделать это на родителе, потому что мы не можем добавить ссылку на потомка (так как потомок уже ссылается на родителя), поэтому де / сериализатор не будет знать, на какого потомка действовать.

Чтобы добавить дополнительный уровень сложности, объект, с которым у меня возникла проблема, фактически де / сериализуется как часть большей сериализации с помощью следующего свойства родительского объекта:

    [XmlElement("ShippingAddress")]
    public Location ShippingAddress
    {
        get { return _shippingAddress; }
        set { _shippingAddress = value; }
    }

Проблема в том, что тип местоположения здесь является дочерним типом местоположения. Таким образом, де-сериализуются только свойства в дочернем типе ... все свойства в родительском типе (также называемом Location, но в пространстве имен difnet) не являются.

это делает это понятнее?

1 Ответ

1 голос
/ 25 июня 2010

XmlSerializer имеет конструктор , который принимает массив типов, называемых "extraTypes".Типы в этом массиве будут доступны во время сериализации и десериализации, как если бы вы добавили атрибуты XmlInclude.

var serializer = new XmlSerializer(typeof(Canine), new Type[] { typeof(Dog) });

Обновление: этот подход работает, если ваш Xml включает атрибут xsi:type, когда тип отличается от того, который был объявлен в корневом объекте.Похоже, вы можете захотеть просто всегда десериализовать это свойство как другой тип.В этом случае вы можете использовать XmlAttributeOverrides для замены метаданных исходных типов.Создание XmlSerializer следующим образом:

var overrides = new XmlAttributeOverrides();
var xmlAttributes = new XmlAttributes();
xmlAttributes.XmlElements.Add(new XmlElementAttribute("ShippingAddress", typeof(ITSM.Location)));
overrides.Add(typeof(Order), "Location", xmlAttributes);
var ser = new XmlSerializer(typeof(Order), overrides);

будет иметь тот же эффект, что и замена атрибутов свойства Order.Location на:

[XmlElement("ShippingAddress", typeof(ITSM.Location))]
...