首页 文章

XmlSerializer - 反映类型时出错

提问于
浏览
318

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

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

我得到一个例外说:

反映类型的错误 .

在数据类内部还有另一个复合对象 . 这是否还需要具有 [Serializable] 属性,或者将其置于顶层对象上,是否以递归方式将其应用于内部的所有对象?

16 回答

  • 1

    [System.Xml.Serialization.XmlElementAttribute(“strFieldName”,Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

    //要么

    [XmlIgnore] string [] strFielsName {get; set;}

  • 6

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

  • 7

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

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

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

  • 0

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

  • 108

    我遇到了类似的问题,结果发现序列化程序无法区分我使用相同名称的两个类(一个是另一个类的子类) . 内部异常看起来像这样:

    'Types BaseNamespace.Class1'和'BaseNamespace.SubNamespace.Class1'都使用来自命名空间''的XML类型名称'Class1' . 使用XML属性为类型指定唯一的XML名称和/或命名空间 .

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

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

    [XmlType("BaseNamespace.Class1")]
    

    注意:如果您有更多层类,则还需要为它们添加属性 .

  • 4

    另请注意 XmlSerializer 无法序列化抽象属性..请参阅我的问题here(我已经添加了解决方案代码)..

    XML Serialization and Inherited Types

  • 0

    我最常见的原因:

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

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

    由于 XMLSerializer 是黑盒子,如果要进一步调试序列化过程,请检查这些链接 .

    Changing where XmlSerializer Outputs Temporary Assemblies

    HOW TO: Debug into a .NET XmlSerializer Generated Assembly

  • 3

    如果您需要处理特定属性(即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 .1505708_ .


    文章说:

    IXmlSerializable包含在官方文档中,但文档声明它不是供公众使用的,除此之外不提供任何信息 . 这表明开发团队希望保留修改,禁用甚至完全删除此可扩展性挂钩的权利 . 但是,只要你愿意接受这种不确定性并处理未来可能发生的变化,就没有任何理由你无法利用它 .

    因为这个,我建议你实现自己的 IXmlSerializable 类,以避免太复杂的实现 .

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

  • 22

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

    我找到了一份关于here的作品 .

  • 5

    我最近在添加新属性时在Web引用分部类中得到了这个 . 自动生成的类正在添加以下属性 .

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

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

  • 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正在使用公共属性的反射 .

  • 2

    我刚刚得到同样的错误,发现 IEnumerable<SomeClass> 类型的属性是问题所在 . 看来 IEnumerable 无法直接序列化 .

  • 0

    我有一种情况,订单对于连续的两个元素是相同的

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

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

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

    当我更改代码以便为类中的每个新属性递增1时,错误就会消失远 .

  • 5

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

  • 0

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

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

相关问题