XML десериализация унаследованных объектов - PullRequest
0 голосов
/ 25 октября 2009

У меня есть объект InputFile, в котором есть массивы и объекты для хранения содержимого файла. У меня также есть ABCFile и XYZFile, которые оба унаследованы от InputFile, которые будут считывать файлы различных типов и сохранять их в проецируемых элементах InputFile.

Поскольку сериализация и десериализация обоих этих объектов идентичны родительскому объекту, я реализовал стандартный интерфейс сериализации XML для родительского объекта. Во время десериализации считываются несколько параметров, вызывается функция Read (для загрузки файла), а затем десериализация завершается.

Сериализация работает отлично, но десериализация (из List<InputFile>) не работает, потому что десериализатор вызывает функцию-заглушку Read родительского файла вместо ABCFile или XYZFile.

Как я могу заставить десериализацию распознать правильный тип объекта для использования? Возможно, у моего List<InputFile> будет сочетание типов файлов.

Спасибо

Код, который я использую для сериализации объекта:

public class InputFileHolder : IXmlSerializable {
...
public void WriteXml(XmlWriter w) {
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("", "");

    XmlSerializer ifXml = new XmlSerializer(typeof(List<InputFile>));
    ifXml.Serialize(w, InputFiles, ns);

    //More serialization
}

Есть идеи, как сохранить тип объекта, когда я настраиваю сериализацию List?

1 Ответ

7 голосов
/ 25 октября 2009

Попробуйте

[XmlArray]
[XmlArrayItem(ElementName="ABCFile", Type=typeof(ABCFile))]
[XmlArrayItem(ElementName="XYZFile", Type=typeof(XYZFile))]
public List<InputFile> InputFileList
{
   get;
   set;
}

Это будет указывать сериализатору, что, хотя это и есть список InputFile, в этом списке будут храниться два производных типа. Скорее всего, он будет использовать конкретные версии методов для каждого.

Если не получится, дайте мне знать.

Редактировать на основе вашего комментария

Я не понимаю, как это может происходить.

Я тестировал следующие классы:

public class InputFile
{
    public String InputfileCommonProperty { get; set; }
}

public class ABCFile : InputFile
{
    public String ABCSpecificProperty { get; set; }
}

public class XYZFile : InputFile
{
    public String XYZSpecificProperty { get; set; }
}

public class InputFileHolder
{
    public InputFileHolder()
    {
        InputFileList = new List<InputFile>();
    }

    [XmlArray]
    [XmlArrayItem(ElementName = "ABCFile", Type = typeof(ABCFile))]
    [XmlArrayItem(ElementName = "XYZFile", Type = typeof(XYZFile))]
    public List<InputFile> InputFileList { get; set; }
}

Моя основная программа выглядит так:

static void Main(string[] args)
{
    InputFileHolder fileHolder = new InputFileHolder();
    fileHolder.InputFileList.Add(
        new ABCFile()
        {
            InputfileCommonProperty = "This is a common property",
            ABCSpecificProperty = "This is a class specific property"
        });

    XmlSerializer serializer = new XmlSerializer(typeof(InputFileHolder));
    MemoryStream memoryStream = new MemoryStream();
    serializer.Serialize(memoryStream, fileHolder);

    System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
    String serializedString = enc.GetString(memoryStream.ToArray());
}

И, наконец, содержимое serializedString:

<?xml version="1.0"?>
<InputFileHolder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <InputFileList>
    <ABCFile>
      <InputfileCommonProperty>This is a common property</InputfileCommonProperty>
      <ABCSpecificProperty>This is a class specific property</ABCSpecificProperty>
    </ABCFile>
  </InputFileList>
</InputFileHolder>

Видишь? Сериализатор знает, что это ABCFile, а не универсальный InputFile.

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