序列化与反序列化
2017-06-04 16:59 Dirichlet 阅读(302) 评论(0) 编辑 收藏 举报using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization; using System.IO; using System.Globalization; namespace SerializeSample { class Program { static void Main(string[] args) { XmlSerializer serializer = new XmlSerializer(typeof(TemplateDescription[])); StringWriter writer = new StringWriter(CultureInfo.InvariantCulture); List<TemplateDescription> list = new List<TemplateDescription>(); TemplateDescription template = new TemplateDescription("aaa", "bbb", 100); template.ObjectValue = new int[2] { 1, 2 }; TemplateDescription template2 = new TemplateDescription("mmm", "nnn", 101); template2.ObjectValue = new byte[2] { 3, 4 }; list.Add(template); list.Add(template2); // Serialize serializer.Serialize(writer, list.ToArray()); File.WriteAllText(@"d:\serialize.txt", writer.ToString()); Console.WriteLine(writer.ToString()); // DeSerialize TemplateDescription[] test = (TemplateDescription[])serializer.Deserialize(new StringReader(writer.ToString())); Console.WriteLine(test[0].ToString()); } } [XmlInclude(typeof(int[]))] public class TemplateDescription { public TemplateDescription() { this.Name = string.Empty; this.Description = string.Empty; this.ID = 0; this.ObjectValue = null; } public TemplateDescription(string name, string description, int id) { this.Name = name; this.Description = description; this.ID = id; } public string Name { get; set; } public string Description { get; set; } public int ID { get; set; } [XmlElement("Value")] public object ObjectValue { get; set; } [XmlIgnore] public int[] IntegerArrayValue { get { return (int[])ObjectValue; } set { ObjectValue = value; } } [XmlIgnore] public byte[] ByteArrayValue { get { return (byte[])ObjectValue; } set { ObjectValue = value; } } } }
xml format的序列化只是针对公有属性。
1. 序列化数组,需要指定特质属性[XmlArrayItem(typeof(...))]。
如果不指定则有可能不能正确序列化,从实验看int数组不指定也可以正确序列化,byte数组就必须得指定。如下:
public class MyClass { public int[] IDs { get; set; } public byte[] BTs { get; set; } public char Charactor { get; set; } public MyClass() { this.IDs = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; this.BTs = new byte[] { 121, 122, 123, 124, 255, 201 }; this.Charactor = 'a'; } }
序列化结果,BTs看上去不正确,其实是经过了based64编码的结果,是正确的。但是如果想得到显式的结果最好加上[XmlArrayItem(typeof(byte))]。
<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<IDs>
<int>1</int>
<int>2</int>
<int>3</int>
<int>4</int>
<int>5</int>
<int>6</int>
<int>7</int>
<int>8</int>
<int>9</int>
<int>0</int>
</IDs>
<BTs>eXp7fP/J</BTs>
<Charactor>97</Charactor>
</MyClass>
加上特制属性:
public class MyClass { public int[] IDs { get; set; } [XmlArrayItem(typeof(byte))] public byte[] BTs { get; set; } public char Charactor { get; set; } public MyClass() { this.IDs = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; this.BTs = new byte[] { 121, 122, 123, 124, 255, 201 }; this.Charactor = 'a'; } } static void Test5() { XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); StringWriter writer = new StringWriter(); MyClass myObject = new MyClass(); serializer.Serialize(writer, myObject); Console.WriteLine(writer.ToString()); }
序列化正确:
<?xml version="1.0" encoding="utf-16"?> <MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <IDs> <int>1</int> <int>2</int> <int>3</int> <int>4</int> <int>5</int> <int>6</int> <int>7</int> <int>8</int> <int>9</int> <int>0</int> </IDs> <BTs> <unsignedByte>121</unsignedByte> <unsignedByte>122</unsignedByte> <unsignedByte>123</unsignedByte> <unsignedByte>124</unsignedByte> <unsignedByte>255</unsignedByte> <unsignedByte>201</unsignedByte> </BTs> <Charactor>97</Charactor> </MyClass>
2. 当某个需要序列化的field或者property具有不确定的类型时,如果要正确序列化它必须在类型上指定[XmlInclude(typeof(...)),XmlInclude(typeof(...))]属性,标识property可能的类型。
如下,public object ObjectValue { get; set; }属性可能是int[],byte[], 所以TemplateDescription加XmlInclude属性。
[XmlInclude(typeof(byte[])), XmlInclude(typeof(int[]))]
public class TemplateDescription
Notes:
只加[XmlInclude(typeof(int[]))]也可以正确序列化byte[]数组的情况。
[XmlInclude(typeof(int[]))]
public class TemplateDescription
只不过 byte[]数组序列化为based64编码结果<Value xsi:type="xsd:base64Binary">AwQ=</Value>,请考虑序加[XmlArrayItem(typeof(byte))] 。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Xml.Serialization; 6 using System.IO; 7 using System.Globalization; 8 9 namespace SerializeSample 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 XmlSerializer serializer = new XmlSerializer(typeof(TemplateDescription[])); 16 StringWriter writer = new StringWriter(CultureInfo.InvariantCulture); 17 18 List<TemplateDescription> list = new List<TemplateDescription>(); 19 TemplateDescription template = new TemplateDescription("aaa", "bbb", 100); 20 template.ObjectValue = new int[2] { 1, 2 }; 21 TemplateDescription template2 = new TemplateDescription("mmm", "nnn", 101); 22 template2.ObjectValue = new byte[2] { 3, 4 }; 23 24 list.Add(template); 25 list.Add(template2); 26 27 // Serialize 28 serializer.Serialize(writer, list.ToArray()); 29 File.WriteAllText(@"d:\serialize.txt", writer.ToString()); 30 Console.WriteLine(writer.ToString()); 31 32 // DeSerialize 33 TemplateDescription[] test = (TemplateDescription[])serializer.Deserialize(new StringReader(writer.ToString())); 34 Console.WriteLine(test[0].ToString()); 35 } 36 } 37 38 [XmlInclude(typeof(byte[])), XmlInclude(typeof(int[]))] 39 public class TemplateDescription 40 { 41 public TemplateDescription() 42 { 43 this.Name = string.Empty; 44 this.Description = string.Empty; 45 this.ID = 0; 46 this.ObjectValue = null; 47 } 48 49 public TemplateDescription(string name, string description, int id) 50 { 51 this.Name = name; 52 this.Description = description; 53 this.ID = id; 54 } 55 56 public string Name { get; set; } 57 public string Description { get; set; } 58 public int ID { get; set; } 59 60 [XmlElement("Value")] 61 public object ObjectValue { get; set; } 62 63 [XmlIgnore] 64 public int[] IntegerArrayValue 65 { 66 get { return (int[])ObjectValue; } 67 set { ObjectValue = value; } 68 } 69 70 [XmlIgnore] 71 public byte[] ByteArrayValue 72 { 73 get { return (byte[])ObjectValue; } 74 set { ObjectValue = value; } 75 } 76 } 77 78 }
1 <?xml version="1.0" encoding="utf-16"?> 2 <ArrayOfTemplateDescription xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 3 <TemplateDescription> 4 <Name>aaa</Name> 5 <Description>bbb</Description> 6 <ID>100</ID> 7 <Value xsi:type="ArrayOfInt"> 8 <int>1</int> 9 <int>2</int> 10 </Value> 11 </TemplateDescription> 12 <TemplateDescription> 13 <Name>mmm</Name> 14 <Description>nnn</Description> 15 <ID>101</ID> 16 <Value xsi:type="xsd:base64Binary">AwQ=</Value> 17 </TemplateDescription> 18 </ArrayOfTemplateDescription>
二.
注意:当类成员变量中出现不能被序列化的类或接口时候我们要通过
[NonSerialized] 只针对成员变量
[XmlIgnore] 针对成员变量和属性,只针对XML序列化
标记其不被序列化和反序列化
特别注意:要使某属性在XML序列化过程中不被序列化只能使用[XmlIgnore],[NonSerialized]无效
三.
“上午同事问我一个问题,实体序列化时报了一个错:The type ConsoleTest.Item was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. 分析之后,发现了问题,原来被序列化的实体其中一个Property的类型是Object,但是实例化时给这个Property赋了一个自定义的Item,因此序列化未通过。之后,在Property上加上属性[XmlElement(typeof(Item))]即可序列化成功。
利用Xml序列化技术进行开发有一段时间了,总结了此应用的一些经验,供网友分享。”
http://blog.csdn.net/henrylubin/article/details/2047671
扩展问题:如果Object在某时刻又被赋值为其他非item对象了呢?Property上加上属性[XmlElement(typeof(Item))]还是不够彻底,最好在类上加
[XmlInclude(typeof(...)), XmlInclude(typeof(...))]
所有的Attribute Class:
http://msdn.microsoft.com/en-us/library/system.attribute.aspx#inheritanceContinued