Answers:
查看您所得到的内部异常。它将告诉您序列化哪个字段/属性。
您可以通过使用[XmlIgnore]
属性装饰字段/属性来将它们从xml序列化中排除。
XmlSerializer
不使用该[Serializable]
属性,因此我怀疑这是问题所在。
IList
必要的List
。
请记住,序列化的类必须具有默认(即无参数)构造函数。如果根本没有构造函数,那很好。但是如果您有一个带参数的构造函数,则还需要添加默认的构造函数。
我有一个类似的问题,事实证明,序列化程序无法区分同名的两个类(一个是另一个的子类)。内部异常如下所示:
'类型BaseNamespace.Class1'和'BaseNamespace.SubNamespace.Class1'都使用名称空间''中的XML类型名称'Class1'。使用XML属性为类型指定唯一的XML名称和/或名称空间。
其中BaseNamespace.SubNamespace.Class1是BaseNamespace.Class1的子类。
我需要做的是向其中一个类添加一个属性(我添加到基类中):
[XmlType("BaseNamespace.Class1")]
注意:如果您有更多层的类,则还需要向它们添加一个属性。
另外要注意,XmlSerializer
不能序列抽象属性..见我的问题在这里(我已经添加了解决方案的代码)..
我最常见的原因:
- the object being serialized has no parameterless constructor
- the object contains Dictionary
- the object has some public Interface members
序列化图中的所有对象都必须可序列化。
由于XMLSerializer
是黑匣子,如果您想进一步调试序列化过程,请检查这些链接。
如果需要处理特定的属性(即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包含在官方文档中,但该文档指出,该文档仅供公众使用,不提供任何其他信息。这表明开发团队希望保留修改,禁用甚至完全删除此可扩展性的权利。但是,只要您愿意接受这种不确定性并应对将来可能发生的变化,就没有任何理由不能利用它。
因此,我建议您实现自己的IXmlSerializable
类,以避免太多复杂的实现。
... 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在公共属性上使用反射。
我遇到的情况是,连续两个元素的顺序相同
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]
....一些代码...
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]
当我更改代码以将类中每个新Property的顺序递增一时,错误消失了。
我一直在使用NetDataSerialiser
该类来序列化我的域类。NetDataContractSerializer类。
域类在客户端和服务器之间共享。
我遇到了同样的问题,在我的情况下,该对象具有ReadOnlyCollection。集合必须实现Add方法才能可序列化。
到目前为止,我对这里描述的所有解决方案都略有不同,因此对于任何未来的文明来说,这都是我的!
我已将数据类型声明为“时间”,因为原始类型为a TimeSpan
,随后更改为String
:
[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=3)]
但是实际类型是字符串
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}
通过删除该DateType
属性Xml
可以序列化
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}