Как сериализовать производный класс в качестве его базового класса - PullRequest
6 голосов
/ 01 декабря 2009

У меня есть производный класс, который добавляет только методы к базовому классу. Как можно сериализовать производный класс, чтобы он соответствовал сериализации базового класса? т.е. сериализованный xml производного класса должен выглядеть следующим образом:

<BaseClass>
  ...
</BaseClass>

например. Следующее будет выбрасывать InvalidOperationException «Тип DerivedClass не ожидался. Используйте атрибут XmlInclude или SoapInclude, чтобы указать типы, которые статически не известны.»

Class BaseClass {}

Class DerivedClass : BaseClass {}

DerivedClass derived = new DerivedClass();

StreamWriter stream = new StreamWriter("output file path");
XmlSerializer serializer = new XmlSerializer(GetType(BaseClass));
serializer(stream, derived);

Ответы [ 4 ]

4 голосов
/ 01 декабря 2009

Вам нужно будет передать GetType (DerivedClass) в конструктор сериализатора, он должен соответствовать типу объекта, который вы сериализуете. Вы можете использовать атрибут <XmlRoot> для переименования в корневой элемент. Этот пример кода работал как задумано:

using System;
using System.Xml.Serialization;
using System.IO;

class Program {
  static void Main(string[] args) {
    var obj = new DerivedClass();
    obj.Prop = 42;
    var xs = new XmlSerializer(typeof(DerivedClass));
    var sw = new StringWriter();
    xs.Serialize(sw, obj);
    Console.WriteLine(sw.ToString());

    var sr = new StringReader(sw.ToString());
    var obj2 = (BaseClass)xs.Deserialize(sr);
    Console.ReadLine();
  }
}

public class BaseClass {
  public int Prop { get; set; }
}
[XmlRoot("BaseClass")]
public class DerivedClass : BaseClass { }
1 голос
/ 29 марта 2013

Вы также можете реализовать интерфейс ICloneable для BaseClass и затем выполнить:

var sw = new StringWriter()

var base = (derived as BaseClass).Clone()
var serializer = new XmlSerializer(typeof(BaseClass))
serializer.Serialize(sw, base)

Console.WriteLine(sw.ToString())

Не идеальный подход, но если ваш базовый класс простой, то он также должен работать.

0 голосов
/ 01 декабря 2009

После небольшого поиска в Google;) Я могу сказать, что вам понадобится еще немного кода и реализовать IXmlSerializable для вашего базового класса, объявив все методы интерфейса как виртуальные и переопределив их в производном классе. Вот пример темы и аналогичная проблема , решенная с помощью упомянутого интерфейса.

0 голосов
/ 01 декабря 2009

Я не пробовал, но разве вы не можете разыграть его?

serializer(stream, (BaseClass)derived);

Редактировать

Кроме того, если вы хотите иметь один XmlSerialiser, который может работать с несколькими производными классами и базовым классом, вам необходимо указать все типы в конструкторе XmlSerialiser.

  XmlSerializer serializer = new XmlSerializer(typeof(BaseClass), new Type[] {typeof(DerivedClass)});

Тогда он с радостью сериализует несколько типов. Однако вам также придется использовать решение, упомянутое выше, чтобы получить выходной XML для соответствия между классами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...