使用C#.NET 2.0,我有一个复合数据类,它具有[Serializable]
属性。我正在创建一个XMLSerializer
类并将其传递给构造函数:
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
我得到一个例外说:
有反映类型的错误。
在数据类中,还有另一个复合对象。这是否还需要具有[Serializable]
属性,或者将它放在顶层对象上,是否以递归方式将其应用于内部的所有对象?
答案 0 :(得分:401)
查看您获得的内部异常。它将告诉您序列化时遇到问题的字段/属性。
您可以通过使用[XmlIgnore]
属性进行装饰来排除xml序列化中的字段/属性。
我认为XmlSerializer
不使用[Serializable]
属性,所以我怀疑这是问题所在。
答案 1 :(得分:108)
请记住,序列化类必须具有默认(即无参数)构造函数。如果你根本没有构造函数,那很好;但是如果你有一个带参数的构造函数,你也需要添加默认值。
答案 2 :(得分:24)
我遇到了类似的问题,结果发现序列化程序无法区分我使用相同名称的两个类(一个是另一个的子类)。内部异常看起来像这样:
'Types BaseNamespace.Class1'和'BaseNamespace.SubNamespace.Class1'都使用来自命名空间''的XML类型名称'Class1'。使用XML属性为类型指定唯一的XML名称和/或命名空间。
其中BaseNamespace.SubNamespace.Class1是BaseNamespace.Class1的子类。
我需要做的是为其中一个类添加一个属性(我添加到基类中):
[XmlType("BaseNamespace.Class1")]
注意:如果您有更多层类,则还需要为它们添加属性。
答案 3 :(得分:7)
另请注意,XmlSerializer
无法序列化抽象属性。请参阅我的问题here(我已将解决方案代码添加到其中)..
答案 4 :(得分:6)
我最常见的原因:
- the object being serialized has no parameterless constructor
- the object contains Dictionary
- the object has some public Interface members
答案 5 :(得分:5)
序列化图中的所有对象都必须是可序列化的。
由于XMLSerializer
是黑盒子,如果要进一步调试序列化过程,请检查这些链接。
答案 6 :(得分:5)
如果你需要处理特定的属性(即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
}
有一个有趣的article,它展示了一种优雅的方法来实现一种“扩展”XmlSerializer的复杂方法。
文章说:
IXmlSerializable包含在官方文档中,但文档声明它不是供公众使用的,除此之外不提供任何信息。这表明开发团队希望保留修改,禁用甚至完全删除此可扩展性挂钩的权利。但是,只要您愿意接受这种不确定性并处理未来可能发生的变化,就没有任何理由不能利用它。
因为这个,我建议你实现自己的IXmlSerializable
类,以避免太复杂的实现。
...使用反射实现我们的自定义XmlSerializer
类可能很简单。
答案 7 :(得分:4)
我发现.Net 2.0中的Dictionary类不能使用XML进行序列化,但在使用二进制序列化时序列化很好。
我找到了here的作品。
答案 8 :(得分:3)
我最近在添加新属性时在Web引用分部类中得到了这个。自动生成的类正在添加以下属性。
[System.Xml.Serialization.XmlElementAttribute(Order = XX)]
我需要添加一个类似的属性,其序列比自动生成的序列中的最后一个高一个,这为我修复了它。
答案 9 :(得分:2)
我也认为Serializable属性必须在对象上,但除非我是一个完整的菜鸟(我正处于深夜编码会话中),否则以下工作来自SnippetCompiler:< / p>
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正在对公共属性使用反射。
答案 10 :(得分:2)
我遇到了同样的错误,发现问题类型为IEnumerable<SomeClass>
的属性。看来IEnumerable
无法直接序列化。
相反,可以使用List<SomeClass>
。
答案 11 :(得分:1)
有时,这种类型的错误是因为您没有没有参数的类构造器
答案 12 :(得分:1)
我遇到的情况是,连续两个元素的顺序相同
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]
....一些代码......
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]
当我更改代码以便为类中的每个新属性增加一个顺序时,错误就消失了。
答案 13 :(得分:0)
我一直在使用NetDataSerialiser
类进行序列化
我的域类。 NetDataContractSerializer Class
域类在客户端和服务器之间共享。
答案 14 :(得分:0)
[System.Xml.Serialization.XmlElementAttribute(&#34; strFieldName&#34;,Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
//或
[XmlIgnore] string [] strFielsName {get; set;}
答案 15 :(得分:0)
我有同样的问题,在我的情况下,该对象有一个ReadOnlyCollection。集合必须实现Add方法才能进行序列化。
答案 16 :(得分:0)
到目前为止,我对这里描述的所有解决方案都略有不同,因此对于任何未来的文明,这都是我的!
我已声明数据类型为“时间”,因为原始类型为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");
}
}
答案 17 :(得分:0)
当我创建一个具有数据类型-Type
的属性时,我遇到了同样的错误。对此,我遇到了一个错误-反映类型的错误。我一直从调试坞站检查每个异常的'InnerException',并获得特定的字段名称(Type
)。解决方案如下:
[XmlIgnore]
public Type Type { get; set; }
答案 18 :(得分:0)
另请注意,您无法序列化用户界面控件,并且您要传递到剪贴板的任何对象必须是可序列化的,否则无法传递给其他进程。