XmlSerializer - 反映类型时出错

发布于 2024-07-06 05:45:53 字数 377 浏览 6 评论 0原文

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

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

我收到一个异常:

反映类型时出错。

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

Using C# .NET 2.0, I have a composite data class that does have the [Serializable] attribute on it. I am creating an XMLSerializer class and passing that into the constructor:

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

I am getting an exception saying:

There was an error reflecting type.

Inside the data class there is another composite object. Does this also need to have the [Serializable] attribute, or by having it on the top object, does it recursively apply it to all objects inside?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

追星践月 2024-07-13 05:45:55

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

    [XmlIgnore]
    public Type Type { get; set; }

I was getting the same error when I created a property having a datatype - Type. On this, I was getting an error - There was an error reflecting type. I kept checking the 'InnerException' of every exception from the debug dock and got the specific field name (which was Type) in my case. The solution is as follows:

    [XmlIgnore]
    public Type Type { get; set; }
深府石板幽径 2024-07-13 05:45:55

我遇到过一种情况,连续两个元素的顺序相同

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

......一些代码......

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

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

I had a situation where the Order was the same for two elements in a row

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

.... some code ...

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

When I changed the code to increment the order by one for each new Property in the class, the error went away.

梦年海沫深 2024-07-13 05:45:55

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

Also note that you cannot serialize user interface controls and that any object you want to pass onto the clipboard must be serializable otherwise it cannot be passed across to other processes.

无需解释 2024-07-13 05:45:55

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

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

I have been using the NetDataSerialiser class to serialise
my domain classes. NetDataContractSerializer Class.

The domain classes are shared between client and server.

对你而言 2024-07-13 05:45:55

我遇到了同样的问题,在我的例子中,该对象有一个 ReadOnlyCollection。 集合必须实现 Add 方法才能序列化。

I had the same issue and in my case the object had a ReadOnlyCollection. A collection must implement Add method to be serializable.

烟雨扶苏 2024-07-13 05:45:55

到目前为止,我对这里描述的所有解决方案都略有不同,因此对于任何未来的文明,这里都是我的!

我声明了“时间”数据类型,因为原始类型是 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");
    }
}

I have a slightly different solution to all described here so far, so for any future civilisation here's mine!

I had declared a datatype of "time" as the original type was a TimeSpan and subsequently changed to a String:

[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=3)]

however the actual type was a string

public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}

by removing the DateType property the Xml can be serialized

[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}
太阳公公是暖光 2024-07-13 05:45:55
[System.Xml.Serialization.XmlElementAttribute("strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

或者

[XmlIgnore]
string [] strFielsName {get;set;}
[System.Xml.Serialization.XmlElementAttribute("strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

Or

[XmlIgnore]
string [] strFielsName {get;set;}
夏日落 2024-07-13 05:45:54

如果您需要处理特定属性(即字典或任何类),您可以实现 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 的复杂方法。


文章说:

官方文档中介绍了 IXmlSerialized,但文档指出它不适合公共使用,并且没有提供除此之外的任何信息。 这表明开发团队希望保留修改、禁用甚至完全删除此扩展性钩子的权利。 然而,只要您愿意接受这种不确定性并应对未来可能发生的变化,就没有理由不能利用它。

因此,我建议实现您自己的 IXmlSerialized 类,以避免过于复杂的实现。

...使用反射实现我们的自定义 XmlSerializer 类可能很简单。

If you need to handle specific attributes (i.e. Dictionary, or any class), you can implement the IXmlSerialiable interface, which will allow you more freedom at the cost of more verbose coding.

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
}

There is an interesting article, which show an elegant way to implements a sophisticated way to "extend" the XmlSerializer.


The article say:

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.

Because this, I suggest to implement you're own IXmlSerializable classes, in order to avoid too much complicated implementations.

...it could be straightforward to implements our custom XmlSerializer class using reflection.

迷途知返 2024-07-13 05:45:54

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

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

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

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

All the objects in the serialization graph have to be serializable.

Since XMLSerializer is a blackbox, check these links if you want to debug further into the serialization process..

Changing where XmlSerializer Outputs Temporary Assemblies

HOW TO: Debug into a .NET XmlSerializer Generated Assembly

风为裳 2024-07-13 05:45:54

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

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

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

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

[XmlType("BaseNamespace.Class1")]

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

I had a similar problem, and it turned out that the serializer could not distinguish between 2 classes I had with the same name (one was a subclass of the other). The inner exception looked like this:

'Types BaseNamespace.Class1' and 'BaseNamespace.SubNamespace.Class1' both use the XML type name, 'Class1', from namespace ''. Use XML attributes to specify a unique XML name and/or namespace for the type.

Where BaseNamespace.SubNamespace.Class1 is a subclass of BaseNamespace.Class1.

What I needed to do was add an attribute to one of the classes (I added to the base class):

[XmlType("BaseNamespace.Class1")]

Note: If you have more layers of classes you need to add an attribute to them as well.

千紇 2024-07-13 05:45:54

我最常见的原因:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members

Most common reasons by me:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members
国际总奸 2024-07-13 05:45:54

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

XML 序列化和继承类型< /a>

Also be aware that XmlSerializer cannot serialize abstract properties.. See my question here (which I have added the solution code to)..

XML Serialization and Inherited Types

旧时光的容颜 2024-07-13 05:45:54

我刚刚遇到了同样的错误,并发现 IEnumerable 类型的属性是问题所在。 看来 IEnumerable 无法直接序列化。

相反,可以使用 List

I just got the same error and discovered that a property of type IEnumerable<SomeClass> was the problem. It appears that IEnumerable cannot be serialized directly.

Instead, one could use List<SomeClass>.

后来的我们 2024-07-13 05:45:54

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

Remember that serialized classes must have default (i.e. parameterless) constructors. If you have no constructor at all, that's fine; but if you have a constructor with a parameter, you'll need to add the default one too.

以歌曲疗慰 2024-07-13 05:45:54

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

我在此处找到了解决方法。

I've discovered that the Dictionary class in .Net 2.0 is not serializable using XML, but serializes well when binary serialization is used.

I found a work around here.

寄风 2024-07-13 05:45:54

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

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

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

I recently got this in a web reference partial class when adding a new property. The auto generated class was adding the following attributes.

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

I needed to add a similar attribute with an order one higher than the last in the auto generated sequence and this fixed it for me.

凉薄对峙 2024-07-13 05:45:54

我也认为可序列化属性必须位于对象上,但除非我是一个完全的菜鸟(我正在深夜编码会话中),否则以下内容来自 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 正在使用公共属性的反射。

I too thought that the Serializable attribute had to be on the object but unless I'm being a complete noob (I am in the middle of a late night coding session) the following works from the 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();
        }
    }

}

I would imagine that the XmlSerializer is using reflection over the public properties.

灼疼热情 2024-07-13 05:45:54

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

Sometime, this type of error is because you dont have constructur of class without argument

仅此而已 2024-07-13 05:45:53

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

您可以通过使用 [XmlIgnore] 属性。

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

Look at the inner exception that you are getting. It will tell you which field/property it is having trouble serializing.

You can exclude fields/properties from xml serialization by decorating them with the [XmlIgnore] attribute.

XmlSerializer does not use the [Serializable] attribute, so I doubt that is the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文