2008-09-13 2 views
298

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

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

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

Был ошибку типа отражающей.

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

ответ

379

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

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

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

+11

У моего объекта было поле Ури, которое вызвало это исключение; класс Uri не имеет конструктора без параметров. Спасибо за совет. – ford 2011-10-28 21:45:16

+7

Пришел к поиску google - моя конкретная проблема имела свойство в моем классе «быть сериализованным» как «IList», когда ему нужно было «List». – 2012-10-08 13:06:59

+7

Как смотреть на «внутреннее исключение»? – David 2012-12-17 03:47:59

0

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

2

Я тоже думал, что Сериализуемый атрибут должен быть на объект, но если я не являюсь полным 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 использует отражение над публичными свойствами.

105

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

6

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

XML Serialization and Inherited Types

0

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

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

4

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

Я нашел работу вокруг here.

4

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

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


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

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

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

... с помощью отражения может быть легко реализовать наш пользовательский класс XmlSerializer.

3

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

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

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

20

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

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

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

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

[XmlType("BaseNamespace.Class1")] 

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

1

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

1

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

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

.... какой-то код ...

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

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

4

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

- the object being serialized has no parameterless constructor 
- the object contains Dictionary 
- the object has some public Interface members 
0

[System.Xml.Serialization.XmlElementAttribute ("strFieldName", форма = System.Xml.Schema.XmlSchemaForm.Unqualified)]

// Или

[XmlIgnore] строка [] {strFielsName получить; набор;}

0

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