XmlSerializer - произошла ошибка, отражающая тип - PullRequest
323 голосов
/ 13 сентября 2008

Используя C # .NET 2.0, у меня есть составной класс данных, в котором есть атрибут [Serializable]. Я создаю класс XMLSerializer и передаю его в конструктор:

XmlSerializer serializer = new XmlSerializer(typeof(DataClass));

Я получаю исключение, говорящее:

Произошла ошибка при отображении типа.

Внутри класса данных есть еще один составной объект. Должен ли он иметь атрибут [Serializable] или, если он находится на верхнем объекте, рекурсивно ли он применяется ко всем объектам внутри?

Ответы [ 16 ]

402 голосов
/ 13 сентября 2008

Посмотрите на внутреннее исключение, которое вы получаете. Он скажет вам, какое поле / свойство имеет проблемы с сериализацией.

Вы можете исключить поля / свойства из сериализации xml, украсив их атрибутом [XmlIgnore].

Я не думаю, что XmlSerializer использует атрибут [Serializable], поэтому я сомневаюсь, что это проблема.

108 голосов
/ 13 сентября 2008

Помните, что сериализованные классы должны иметь конструкторы по умолчанию (т.е. без параметров). Если у вас нет конструктора вообще, это нормально; но если у вас есть конструктор с параметром, вам также нужно добавить конструктор по умолчанию.

24 голосов
/ 17 сентября 2011

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

Типы BaseNamespace.Class1 и BaseNamespace.SubNamespace.Class1 оба используют имя типа XML, Class1, из пространства имен. Используйте атрибуты XML, чтобы указать уникальное имя XML и / или пространство имен для типа.

Где BaseNamespace.SubNamespace.Class1 является подклассом BaseNamespace.Class1.

Что мне нужно было сделать, это добавить атрибут в один из классов (я добавил в базовый класс):

[XmlType("BaseNamespace.Class1")]

Примечание. Если у вас больше слоев классов, вам также необходимо добавить к ним атрибут.

7 голосов
/ 13 сентября 2008

Также помните, что XmlSerializer не может сериализовать абстрактные свойства. См. Мой вопрос здесь (к которому я добавил код решения) ..

Сериализация XML и унаследованные типы

6 голосов
/ 22 февраля 2014

Наиболее распространенные мной причины:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members
5 голосов
/ 26 апреля 2010

Если вам нужно обрабатывать определенные атрибуты (например, Словарь или любой другой класс), вы можете реализовать интерфейс IXmlSerialiable , который предоставит вам больше свободы за счет более подробного кодирования .

public class NetService : IXmlSerializable
{
    #region Data

        public string Identifier = String.Empty;

        public string Name = String.Empty;

        public IPAddress Address = IPAddress.None;
        public int Port = 7777;

    #endregion

    #region IXmlSerializable Implementation

        public XmlSchema GetSchema() { return (null); }

        public void ReadXml(XmlReader reader)
        {
            // Attributes
            Identifier = reader[XML_IDENTIFIER];
            if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
            if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
        }

        public void WriteXml(XmlWriter writer)
        {
            // Attributes
            writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
            writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
            writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
        }

        private const string XML_IDENTIFIER = "Id";

        private const string XML_NETWORK_ADDR = "Address";

        private const string XML_NETWORK_PORT = "Port";

    #endregion
}

Существует интересная статья , в которой представлен элегантный способ реализации сложного способа "расширения" XmlSerializer.


В статье говорится:

IXmlSerializable описан в официальной документации, но в документации указано, что она не предназначена для публичного использования, и не предоставляет никакой информации, кроме этого. Это указывает на то, что команда разработчиков хотела оставить за собой право изменить, отключить или даже полностью удалить этот механизм расширения в будущем. Однако до тех пор, пока вы готовы принять эту неопределенность и справиться с возможными изменениями в будущем, нет никаких причин, по которым вы не сможете воспользоваться этим.

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

... было бы просто реализовать наш пользовательский класс XmlSerializer, используя отражение.

5 голосов
/ 13 сентября 2008

Все объекты в графе сериализации должны быть сериализуемыми.

Поскольку XMLSerializer является черным ящиком, проверьте эти ссылки, если вы хотите продолжить отладку в процессе сериализации.

Изменение места, где XmlSerializer выводит временные сборки

КАК: Отладка в сгенерированную сборку .NET XmlSerializer

4 голосов
/ 02 июля 2009

Я обнаружил, что класс Dictionary в .Net 2.0 не сериализуется с использованием XML, но хорошо сериализуется при использовании двоичной сериализации.

Я нашел работу около здесь .

3 голосов
/ 17 декабря 2010

Я недавно получил это в частичном классе веб-ссылок при добавлении нового свойства. Сгенерированный автоматически класс добавляет следующие атрибуты.

    [System.Xml.Serialization.XmlElementAttribute(Order = XX)]

Мне нужно было добавить подобный атрибут с порядком на один выше, чем последний в автоматически сгенерированной последовательности, и это исправило его для меня.

2 голосов
/ 12 января 2012

Я только что получил ту же ошибку и обнаружил, что проблема связана со свойством типа IEnumerable<SomeClass>. Похоже, что IEnumerable нельзя сериализовать напрямую.

Вместо этого можно использовать List<SomeClass>.

...