• 使用IXmlSerializable的问题


      最近又开始使用XML了,但今天遇到一个折腾我一下午加一个晚上的时间,终于从网络上找到相关的资料解决了。

         有一个成员是用来存放正则表达式的,由于里面包含其它字符,所以想用CDATA来保存方便查看,所以想到另建一个类再通过继承IXmlSerializable 接口来实现CDATA节点。参照了官方MSDN文档,写了类似以下的代码:

      

    using System;
    using System.Xml;
    using System.Xml.Schema;
    using System.Xml.Serialization;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.IO;
    using System.Diagnostics;
    
    namespace BeiBei.Core.Tests
    {
        [XmlRoot("Worker")]
        public class Worker
        {
            [XmlElement]
            public string JobTitle { get; set; }
    
            [XmlAttribute("active")]
            public bool Active { get; set; }
    
            [XmlElement]
            public string NextPageEncodingName { get; set; }
    
            [XmlElement]
            public Person Person { get; set; }
    
            [XmlElement]
            public Person Person2 { get; set; }
    
        }
    
        public class Person : IXmlSerializable
        {
            // Private state
            private string personName;
    
    
            // Constructors
            public Person(string name)
            {
                personName = name;
            }
    
            public Person()
            {
                personName = null;
            }
    
    
            // Xml Serialization Infrastructure
            public void WriteXml(XmlWriter writer)
            {
                writer.WriteString(personName);
            }
    
            public void ReadXml(XmlReader reader)
            {
                 personName = reader.ReadString();
            }
    
            public XmlSchema GetSchema()
            {
                return (null);
            }
    
    
            // Print
            public override string ToString()
            {
                return (personName);
            }
    
        }
    
        [TestClass]
        public class IXmlSerializableTests
        {
            [TestMethod]
            public void S_Person_Test()
            {
                var p = new Person("Shawn");
    
                XmlSerializer serializer = new XmlSerializer(typeof(Person));
    
                string path = "D:\Test.Person.xml";
                string path2 = "D:\Test.Person.2.xml";
    
                using (var writer = XmlWriter.Create(path))
                {
                    serializer.Serialize(writer, p);
                }
    
                using (var reader = XmlReader.Create(path))
                {
                    var p2 = serializer.Deserialize(reader) as Person;
    
                    using (var writer2 = XmlWriter.Create(path2))
                    {
                        serializer.Serialize(writer2, p2);
                    }
                }
    
                var xml1 = File.ReadAllText(path);
                var xml2 = File.ReadAllText(path2);
                Assert.AreEqual(xml1, xml2);
                Debug.WriteLine(xml2);
            }
    
            [TestMethod]
            public void S_Worker_Test()
            {
                var p = new Person("Shawn");
                var pp = new Person("John");
    
                var w = new Worker()
                {
                    JobTitle = "Boss",
                    Person = p,
                    Person2 = pp,
                    NextPageEncodingName = "gb2312",
                };
    
                XmlSerializer serializer = new XmlSerializer(typeof(Worker));
    
                string path = "D:\Test.Worker.xml";
                string path2 = "D:\Test.Worker.2.xml";
    
                using (var writer = XmlWriter.Create(path))
                {
                    serializer.Serialize(writer, w);
                }
    
                using (var reader = XmlReader.Create(path))
                {
                    var w2 = serializer.Deserialize(reader) as Worker;
    
                    using (var writer2 = XmlWriter.Create(path2))
                    {
                        serializer.Serialize(writer2, w2);
                    }
                }
    
                var xml1 = File.ReadAllText(path);
                var xml2 = File.ReadAllText(path2);
    
                Debug.WriteLine(xml2);
                Assert.AreEqual(xml1, xml2);
            }
        }
    }

      结果Serialize出来的文件是正常的,但Deserialize后文件中,第一个Person之后的其它属性都没有了。

          尝试了很多次,当个PERSON对象序列化/反序列化都是没有问题的,但当对象包括PERSON,且PERSON属性后还定义了其它的属性,尝试添加<XmlElement>之类的特性都没用。结论就是:第一个PERSON属性之后的其它属性一率都没能正常Deserialize。怪自己对这块不了解,更怪MSDN没有写好例子!

          后来在这里找到答案:

          http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly

         

          其实跟属性顺序没有关系,而是我们没有把ReadXml的实现正确地实现了。再改成如下就正常了:

          

            public void ReadXml(XmlReader reader)
            {
                reader.MoveToContent();
                var isEmptyElement = reader.IsEmptyElement;
                reader.ReadStartElement();
    
                if (!isEmptyElement)
                {
                    personName = reader.ReadString();
                    reader.ReadEndElement();
                }
            }
    

      

    终于搞定了,终于可以继续后面的任务!刚过了十二点!


    test account for wechat development
  • 相关阅读:
    Eclipse中显示行号
    PeerSim中一些自己的理解
    迄今为止看过的书籍
    Java程序跨平台运行
    Linux下在PeerSim中运行Chord源代码
    在Eclipse中运行PeerSim的例子
    Ubuntu下安装Java
    Eclipse中自动调整代码
    Eclipse中Outline里各种图标的含义
    Java是如何运行的
  • 原文地址:https://www.cnblogs.com/swlin/p/3393492.html
Copyright © 2020-2023  润新知