在使用XmlSerializer 序列化实体类的时候可能会遇到实体类中含有可空字段序列化的问题,如果我们直接对实体类进行序列化等到的Xml字符后我们查看会发现其中可空字段的xml标记的属性中会加入自动加入很多无用属性。
下面给出一个实例:一个实体类Student 包含一个可空的 int?Age 字段,以及一个XmlSerializer方法。
Student
1 public class Student 2 { 3 public string ID 4 { 5 get; 6 set; 7 } 8 public String Name 9 { 10 get; 11 set; 12 } 13 public string Sex 14 { 15 get; 16 set; 17 } 18 public int? Age 19 { 20 get; 21 set; 22 } 23 24 public string Remark 25 { 26 get; 27 set; 28 } 29 30 public Student() 31 { 32 this.Name = "张三"; 33 this.ID = new Guid().ToString(); 34 this.Sex = "Boy"; 35 this.Remark = "备注。。。。。"; 36 } 37 }
XML序列化方法
1 public string Serialize<T>(T obj) 2 { 3 XmlSerializer serializer = new XmlSerializer(typeof(T)); 4 var xmlns = new XmlSerializerNamespaces(); 5 xmlns.Add(string.Empty, string.Empty); 6 var stream = new MemoryStream(); 7 serializer.Serialize(stream, obj, xmlns); 8 StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8); 9 stream.Position = 0; 10 reader.ReadLine(); 11 return reader.ReadToEnd(); 12 }
当我们传入一个没有设置Age字段属性的Student实体类给序列化函数后得到的结果为:
Serializer Result
1 <Student> 2 <ID>00000000-0000-0000-0000-000000000000</ID> 3 <Name>张三</Name> 4 <Sex>Boy</Sex> 5 <Age d2p1:nil="true" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-instance" /> 6 <Remark>备注。。。。。</Remark> 7 </Student>
我们可以发现其中的<Age d2p1:nil="true" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-instance" />这个标记中加入了一些无效的属性值,这对我们后续处理带来了不便(比如要把xml传递给数据库端的存储过程处理,对这种包含无效字符的xml字段是很不好处理的),因此就需要我们把xml序列化做一些特殊处理。对于这种可空的属性字段如果值为空那么我们可以不序列化它。
那么如何处理才能让XML不去序列化这个可空的Age字段呢?
其实我们可以再实体类中增加一个判断是否序列化的Bool 方法 :格式为 public bool ShouldSerializeAttibute{return Attribute.HasValue;}Attribute与可空属性的名称一样 因此,上面的实体类就可以变成:
Student
1 public class Student 2 { 3 public string ID 4 { 5 get; 6 set; 7 } 8 public String Name 9 { 10 get; 11 set; 12 } 13 public string Sex 14 { 15 get; 16 set; 17 } 18 public int? Age 19 { 20 get; 21 set; 22 } 23 public bool ShouldSerializeAge() 24 { 25 return Age.HasValue; 26 } 27 public string Remark 28 { 29 get; 30 set; 31 } 32 public Student() 33 { 34 this.Name = "张三"; 35 this.ID = new Guid().ToString(); 36 this.Sex = "Boy"; 37 this.Remark = "备注。。。。。"; 38 } 39 }
然后再次序列化,我们可以发现得到的结果如下,其中Age标记已经没有了,正是我们所需要的结果。
new Result
1 <Student> 2 <ID>00000000-0000-0000-0000-000000000000</ID> 3 <Name>张三</Name> 4 <Sex>Boy</Sex> 5 <Remark>备注。。。。。</Remark> 6 </Student>