Десериализация XML не распознает созданные прокси-производные классы - PullRequest
2 голосов
/ 18 апреля 2011

У меня сильная головная боль при попытке десериализации XML в автоматически сгенерированный прокси-класс с производными типами.

Это мой сценарий (работа с Xml.Serialization)

Одна Служба WCF 4.0 Совместное использование (в рамках контракта) следующих типов:

[XmlRootAttribute(Namespace = "", IsNullable = false)]
public class InstallerConfig
{
    [XmlArray]
    [XmlArrayItem(typeof(FileExistsRequisite))]
    [XmlArrayItem(typeof(RegistryKeyExistsRequisite))]
    public List<ModuleRequisite> Prerequisites { /* getter and setter */ }

    ...
}

FileExistsRequisite и RegistryKeyExistsRequisite оба получены из основания ModuleRequisite. Все они определены следующим образом:

[XmlInclude(typeof(FileExistsRequisite))]
[XmlInclude(typeof(RegistryKeyExistsRequisite))]
public class ModuleRequisite
{
    /* some properties here */
}

public class FileExistsRequisite : ModuleRequisite
{
    /* some properties here */
}

public class RegistryKeyExistsRequisite : ModuleRequisite
{
    /* some properties here */
}

Если я попытаюсь сериализовать, а затем десериализовать экземпляр InstallerConfig, он просто сработает (и сериализация, и десериализация работают как положено).

Это результирующий файл XML:

<?xml version="1.0" encoding="utf-8"?>
<InstallerConfig xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Prerequisites>
        <RegistryKeyExistsRequisite>
            <RequisiteOrder>1</RequisiteOrder>
            <!-- Some other elements with their values -->
        </RegistryKeyExistsRequisite>
        <FileExistsRequisite>
            <RequisiteOrder>2</RequisiteOrder>
            <!-- Some other elements with their values -->
        </FileExistsRequisite>
    </Prerequisites>
</InstallerConfig>

Однако, с другой стороны, у меня есть NET 2.0 WinForms Application с WCF, на который ссылается веб-ссылка. Когда я пытаюсь десериализовать ранее сериализованный XML-файл:

XmlSerializer serializer = new XmlSerializer(typeof(WCFWebReference.InstallerConfig));
XmlTextReader stream = new XmlTextReader("deserializedXML.xml");
WCFWebReference.InstallerConfig desInstallerConfig = (WCFWebReference.InstallerConfig)serializer.Deserialize(stream);

Созданный desInstallerConfig объект имеет пустой массив ModuleRequisite объектов (MyNamespace.WCFWebReference.ModuleRequisite[0]) в качестве значения для поля Prerequisite, когда XML фактически имеет два элемента, оба получены из ModuleRequisite.

Что я делаю не так? Так сильно разочарованы этой проблемой: - (

Заранее спасибо.

1 Ответ

0 голосов
/ 19 апреля 2011

Я решил свою проблему.

Сначала я удалил ВСЕ теги оформления XML из свойства Prerequisites в классе InstallerConfig.Это привело к тому, что после сериализации элементы из производных классов в XML отображаются не как <DERIVEDCLASSNAME></DERIVEDCLASSNAME>, а как <BASECLASSNAME xsi:type="DERIVEDCLASSNAME"></BASECLASSNAME>.

. На десериализации при добавлении производных классов я добавлял производные классы в конструктор XmlSerializer как дополнительные типы:

List<Type> extraTypes = new List<Type>() {
    extraTypes.Add(typeof(WCFWebReference.FileExistsRequisite)),
    extraTypes.Add(typeof(WCFWebReference.RegistryKeyExistsRequisite))
};
XmlSerializer serializer = new XmlSerializer(
    typeof(WCFWebReference.InstallerConfig), extraTypes.ToArray());

Это позволяет коду приложения преобразовывать любой производный класс ModuleRequisite в соответствующий ему тип (определенный в xsi:type свойстве XML).

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