使用IXmlSerializable的问题_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 使用IXmlSerializable的问题

使用IXmlSerializable的问题

 2013/10/29 2:57:40  Wizardlsw  博客园  我要评论(0)
  • 摘要:最近又开始使用XML了,但今天遇到一个折腾我一下午加一个晚上的时间,终于从网络上找到相关的资料解决了。有一个成员是用来存放正则表达式的,由于里面包含其它字符,所以想用CDATA来保存方便查看,所以想到另建一个类再通过继承IXmlSerializable接口来实现CDATA节点。参照了官方MSDN文档,写了类似以下的代码:usingSystem;usingSystem.Xml;usingSystem.Xml.Schema;usingSystem.Xml.Serialization
  • 标签:使用 问题 RIA XML

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

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

  

class="brush:csharp;gutter:true;">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();
            }
        }

  

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

 

发表评论
用户名: 匿名