2008-09-13 71 views
298

使用C#.NET 2.0,我有一个组合数据类,其上有[Serializable]属性。我创建一个XMLSerializer类,并传递一个到构造函数:XmlSerializer - 反映类型时出现错误

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

我得到一个异常的说法:

有反映类型错误。

数据类中还有另一个复合对象。这是否也需要具有[Serializable]属性,或者将它放在顶层对象上,是否将其递归应用于所有对象?

回答

379

看看你正在得到的内部异常。它会告诉你哪个字段/属性有序列化的麻烦。

通过使用[XmlIgnore]属性对它们进行修饰,可以从xml序列化中排除字段/属性。

我不认为XmlSerializer使用[Serializable]属性,所以我怀疑这是问题所在。

+11

我的对象有一个Uri字段,这引起了这个异常; Uri类没有无参数的构造函数。谢谢你的提示。 – ford 2011-10-28 21:45:16

+7

在谷歌搜索中遇到了这个问题 - 当我需要成为List时,我的特殊问题是在我的“被序列化”类中拥有一个属性为“IList”。 – 2012-10-08 13:06:59

+7

如何看待“内部例外”? – David 2012-12-17 03:47:59

0

另请注意,您不能序列化用户界面控件,并且要传递到剪贴板的任何对象都必须是可序列化的,否则不能传递给其他进程。

2

我也认为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使用公共属性的反射。

105

请记住,序列化类必须具有默认(即无参数)构造函数。如果你根本没有构造函数,那很好;但是如果你有一个带参数的构造函数,你还需要添加默认的参数。

4

我发现.Net 2.0中的Dictionary类不能使用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

我最近在添加新属性时在Web引用partial类中得到了这个。自动生成的类正在添加以下属性。

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

我需要添加一个类似的属性与自动生成的序列中的顺序一个比过去更高,这个固定为我。

20

我有一个类似的问题,事实证明,序列化程序无法区分我有同名的两个类(一个是另一个的子类)。内部异常如下所示:

'类型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] 的String [] {strFielsName获得;设置;}

0

我有同样的问题,在我的情况下,对象有一个ReadOnlyCollection。集合必须实现Add方法才能被序列化。