zoukankan      html  css  js  c++  java
  • 使用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
  • 相关阅读:
    scss使用指南--每天一点
    Egret引擎开发基础(一)
    vue-awesome-swiper使用自动轮播和循环轮播不生效(loop和autoplay)
    Vue项目中title的设置,使用document.title返回时不生效
    charles系列破解激活注册码
    Vscode中vue项目中无法对js进行提示
    JS数组与对象的遍历方法大全
    手把手教你用webpack3搭建react项目(开发环境和生产环境)(二)
    服务器安装redis-stat和easyNmon
    Shell备份数据库
  • 原文地址:https://www.cnblogs.com/swlin/p/3393492.html
Copyright © 2011-2022 走看看