有一个成员是用来存放正则表达式的,由于里面包含其它字符,所以想用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(); } } |
终于搞定了,终于可以继续后面的任务!刚过了十二点!
联系客服