XmlSerializer - была ошибка, отражающая тип

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

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

Я получаю исключение:

Произошла ошибка, отражающая тип.

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

294
задан leora 13 сент. '08 в 17:40
источник поделиться
16 ответов

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

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

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

374
ответ дан Lamar 13 сент. '08 в 17:53
источник поделиться

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

104
ответ дан Jeremy McGee 13 сент. '08 в 19:23
источник поделиться

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

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

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

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

[XmlType("BaseNamespace.Class1")]

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

20
ответ дан Dennis Calla 17 сент. '11 в 0:51
источник поделиться

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

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

6
ответ дан Rob Cooper 13 сент. '08 в 20:31
источник поделиться

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

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

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

КАК: Отлаживать сборку .NET XmlSerializer

5
ответ дан Gulzar Nazim 13 сент. '08 в 18:05
источник поделиться

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

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

4
ответ дан Charlie Salts 02 июля '09 в 22:32
источник поделиться

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

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members
4
ответ дан Stefan Michev 22 февр. '14 в 15:29
источник поделиться

Если вам нужно обрабатывать определенные атрибуты (например, словарь или любой класс), вы можете реализовать интерфейс 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.

4
ответ дан Luca 26 апр. '10 в 21:34
источник поделиться

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

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

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

3
ответ дан LepardUK 17 дек. '10 в 17:15
источник поделиться

Я тоже думал, что атрибут Serializable должен быть на объекте, но если я не являюсь полным noob (я нахожусь в середине сеанса ночного кодирования), следующие работы из SnippetCompiler:

using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;

public class Inner
{
    private string _AnotherStringProperty;
    public string AnotherStringProperty 
    { 
      get { return _AnotherStringProperty; } 
      set { _AnotherStringProperty = value; } 
    }
}

public class DataClass
{
    private string _StringProperty;
    public string StringProperty 
    { 
       get { return _StringProperty; } 
       set{ _StringProperty = value; } 
    }

    private Inner _InnerObject;
    public Inner InnerObject 
    { 
       get { return _InnerObject; } 
       set { _InnerObject = value; } 
    }
}

public class MyClass
{

    public static void Main()
    {
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
            TextWriter writer = new StreamWriter(@"c:\tmp\dataClass.xml");
            DataClass clazz = new DataClass();
            Inner inner = new Inner();
            inner.AnotherStringProperty = "Foo2";
            clazz.InnerObject = inner;
            clazz.StringProperty = "foo";
            serializer.Serialize(writer, clazz);
        }
        finally
        {
            Console.Write("Press any key to continue...");
            Console.ReadKey();
        }
    }

}

Я бы предположил, что XmlSerializer использует отражение над публичными свойствами.

2
ответ дан Darren 13 сент. '08 в 18:23
источник поделиться

У меня была ситуация, когда порядок был одинаковым для двух элементов в строке

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]

.... некоторый код...

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]

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

1
ответ дан Jeremy Brown 18 дек. '12 в 1:22
источник поделиться

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

1
ответ дан jkokorian 12 янв. '12 в 15:59
источник поделиться

У меня была такая же проблема, и в моем случае у объекта был ReadOnlyCollection. Коллекция должна реализовать метод Add для сериализации.

0
ответ дан Curious Dev 26 мая '17 в 4:19
источник поделиться

[System.Xml.Serialization.XmlElementAttribute( "strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

//Или

[XmlIgnore] string [] strFielsName {get; set;}

0
ответ дан Kiran.Bakwad 16 февр. '17 в 14:48
источник поделиться

Я использую класс NetDataSerialiser для сериализации мои классы домена. класс NetDataContractSerializer.

Классы домена совместно используются клиентом и сервером.

0
ответ дан peterka 16 сент. '08 в 16:14
источник поделиться

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

0
ответ дан Phil Wright 13 сент. '08 в 17:55
источник поделиться

Другие вопросы по меткам или Задайте вопрос