打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

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

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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的实现正确地实现了。再改成如下就正常了:

      

1
2
3
4
5
6
7
8
9
10
11
12
public void ReadXml(XmlReader reader)
{
    reader.MoveToContent();
    var isEmptyElement = reader.IsEmptyElement;
    reader.ReadStartElement();
 
    if (!isEmptyElement)
    {
        personName = reader.ReadString();
        reader.ReadEndElement();
    }
}

  

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

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
VA18.4 序列化
ASP.NET Core MVC 从入门到精通之序列化
WPF 绑定到非FrameworkElement对象
C# 序列化(Serialize)与反序列化(Deserialize)
XML序列化和反序列化
.Net深入实战系列
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服