355

使用 C# .NET 2.0,我有一个复合数据类,它确实具有[Serializable]属性。我正在创建一个XMLSerializer类并将其传递给构造函数:

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

我得到一个例外说:

反映类型有错误。

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

4

19 回答 19

434

看看你得到的内部异常。它会告诉您在序列化时遇到问题的字段/属性。

您可以通过使用属性装饰字段/属性来从 xml 序列化中排除它们[XmlIgnore]

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

于 2008-09-13T14:53:09.820 回答
114

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

于 2008-09-13T16:23:20.480 回答
26

我遇到了类似的问题,结果证明序列化程序无法区分我拥有的两个具有相同名称的类(一个是另一个的子类)。内部异常如下所示:

“Types BaseNamespace.Class1”和“BaseNamespace.SubNamespace.Class1”都使用命名空间“”中的 XML 类型名称“Class1”。使用 XML 属性为类型指定唯一的 XML 名称和/或命名空间。

其中 BaseNamespace.SubNamespace.Class1 是 BaseNamespace.Class1 的子类。

我需要做的是向其中一个类添加一个属性(我添加到基类中):

[XmlType("BaseNamespace.Class1")]

注意:如果您有更多的类层,您还需要为它们添加一个属性。

于 2011-09-16T21:51:10.547 回答
7

另请注意,XmlSerializer无法序列化抽象属性。请在此处查看我的问题(我已将解决方案代码添加到其中)。

XML 序列化和继承类型

于 2008-09-13T17:31:05.900 回答
7

我最常见的原因:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members
于 2014-02-22T12:29:00.810 回答
5

序列化图中的所有对象都必须是可序列化的。

由于XMLSerializer是一个黑盒,如果您想进一步调试序列化过程,请检查这些链接。

更改 XmlSerializer 输出临时程序集的位置

如何:调试到 .NET XmlSerializer 生成的程序集

于 2008-09-13T15:05:24.223 回答
5

如果您需要处理特定的属性(即 Dictionary 或任何类),您可以实现IXmlSerialable接口,这将允许您以更冗长的编码为代价获得更多的自由。

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...使用反射实现我们的自定义类可能很简单。

于 2010-04-26T18:34:26.923 回答
5

我刚遇到同样的错误,发现类型属性IEnumerable<SomeClass>是问题所在。看来IEnumerable不能直接序列化。

相反,可以使用List<SomeClass>.

于 2012-01-12T12:59:07.013 回答
4

我发现 .Net 2.0 中的 Dictionary 类不能使用 XML 序列化,但在使用二进制序列化时可以很好地序列化。

我在这里找到了一份工作。

于 2009-07-02T19:32:19.697 回答
3

我最近在添加新属性时在 web 参考部分类中得到了这个。自动生成的类正在添加以下属性。

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

我需要添加一个类似的属性,其顺序比自动生成的序列中的最后一个高一个,这为我修复了它。

于 2010-12-17T14:15:18.633 回答
2

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

于 2008-09-13T15:23:04.103 回答
2

有时,这种类型的错误是因为您没有没有参数的类的构造

于 2021-02-20T08:50:28.877 回答
1

我有一种情况,其中连续两个元素的顺序相同

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

....一些代码...

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

当我更改代码为类中的每个新属性将顺序增加一时,错误就消失了。

于 2012-12-17T22:22:07.277 回答
1

当我创建具有数据类型 - 的属性时,我遇到了同样的错误Type。在这个问题上,我遇到了一个错误——反映类型有一个错误。我不断检查调试坞中每个异常的“InnerException”,并Type在我的情况下获得了特定的字段名称(即 )。解决方法如下:

    [XmlIgnore]
    public Type Type { get; set; }
于 2019-12-17T10:58:04.863 回答
0

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

于 2008-09-13T14:55:17.693 回答
0

我一直在使用NetDataSerialiser该类来序列化我的域类。NetDataContractSerializer 类

域类在客户端和服务器之间共享。

于 2008-09-16T13:14:18.520 回答
0
[System.Xml.Serialization.XmlElementAttribute("strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

或者

[XmlIgnore]
string [] strFielsName {get;set;}
于 2017-02-16T11:48:17.423 回答
0

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

于 2017-05-26T01:19:58.430 回答
0

到目前为止,我对这里描述的所有解决方案都有一个稍微不同的解决方案,所以对于任何未来的文明,这里都是我的!

我已经声明了“时间”的数据类型,因为原始类型是 aTimeSpan并随后更改为 a 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");
    }
}
于 2019-12-17T10:55:35.803 回答