XmlSerializer-反映类型错误
使用C.NET 2.0,我有一个复合数据类,它确实具有[Serializable]
属性。我正在创建一个XMLSerializer类,并将其传递给构造函数:
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
我正在说一个例外:
There was an error reflecting type.
在数据类内部,还有另一个复合对象。是否还需要具有Serializable属性,还是将其放在顶部对象上,是否将其递归地应用于内部的所有对象?
解决方案
回答
查看我们所得到的内部异常。它会告诉我们序列化哪个字段/属性有问题。
我们可以通过使用[XmlIgnore]属性修饰字段/属性来将它们从xml序列化中排除。
我不认为XmlSerializer
使用[Serializable]
属性,所以我怀疑这是问题所在。
回答
还要注意,我们不能序列化用户界面控件,并且要传递到剪贴板的任何对象都必须可序列化,否则无法传递给其他进程。
回答
序列化图中的所有对象都必须可序列化。
由于XMLSerializer是一个黑盒,因此,如果我们想进一步调试序列化过程,请检查这些链接。
更改XmlSerializer输出临时程序集的位置
如何:调试到.NET XmlSerializer生成的程序集中
回答
我也认为Serializable属性必须在对象上,但是除非我是一个完整的菜鸟(我正在深夜编码会议中),否则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在公共属性上使用反射。
回答
请记住,序列化的类必须具有默认的(即无参数)构造函数。如果根本没有构造函数,那很好。但是如果我们有一个带参数的构造函数,则还需要添加默认的构造函数。
回答
另外请注意,XmlSerializer
不能序列化抽象属性。
XML序列化和继承的类型
回答
我一直在使用NetDataSerialiser类进行序列化
我的网域类别。 NetDataContractSerializer类。
域类在客户端和服务器之间共享。
回答
我发现.Net 2.0中的Dictionary类无法使用XML进行序列化,但是在使用二进制序列化时可以很好地进行序列化。
我在这里找到了工作。
回答
如果我们需要处理特定的属性(即Dictionary或者任何类),则可以实现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 is covered in the official documentation, but the documentation states it's not intended for public use and provides no information beyond that. This indicates that the development team wanted to reserve the right to modify, disable, or even completely remove this extensibility hook down the road. However, as long as you're willing to accept this uncertainty and deal with possible changes in the future, there's no reason whatsoever you can't take advantage of it.
因此,我建议我们实现自己的" IXmlSerializable"类,以避免过于复杂的实现。
...使用反射实现我们自定义的XmlSerializer
类可能很简单。
回答
我最近在添加新属性时将其放在Web参考分部类中。自动生成的类正在添加以下属性。
[System.Xml.Serialization.XmlElementAttribute(Order = XX)]
我需要添加一个类似的属性,其顺序比自动生成的序列中的最后一个顺序高,这对我来说是固定的。