淺談XML與對(duì)象的序列化與反序列化
這篇文章主要講述XML與對(duì)象的序列化與反序列化。并且會(huì)附上一些簡單的序列化與反序列化方法,供大家使用。
假設(shè)我們?cè)谝粋€(gè)Web項(xiàng)目中有這樣兩個(gè)類
- public class Member
- {
- public string Num { get; set; }
- public string Name { get; set; }
- }
- public class Team
- {
- public string Name;
- public List<Member> Members { get; set; }
- }
假設(shè)我們需要把Team類的一個(gè)實(shí)例POST到一個(gè)URL,
當(dāng)然,使用Form隱藏域提交就可以完成該功能。
如果該Team包括30條數(shù)據(jù)呢?
為了區(qū)分每個(gè)Member,我們得給參數(shù)的名字加上后綴。這就要一大串的隱藏域來完成:
- <!--使用Razor來演示-->@model Team
- <form id="submitForm" action="http://www.johnconnor.com/team" method="post">
- <input type="hidden" name="TeamName" value="@Model.Name" />
- <input type="hidden" name="MemberNum1" value="@Model.Members[0].Num" />
- <input type="hidden" name="MemberName1" value="@Model.Members[0].Name" />
- ...<!--省略28X2個(gè)input標(biāo)簽-->
- <input type="hidden" name="MemberNum30" value="@Model.Members[29].Num" />
- <input type="hidden" name="MemberName30" value="@Model.Members[29].Name" />
- </form>
- <script type="text/javascript">
- document.getElementById("submitForm").submit();
- </script>
還敢想象一下如果Team再復(fù)雜一些,嵌套再多一些的情況么?
呃,即使你愿意這么傳數(shù)據(jù),對(duì)方看到一坨參數(shù)名就夠頭疼了。
我們都知道對(duì)象是不能在網(wǎng)絡(luò)中直接傳輸?shù)?,不過還有補(bǔ)救的辦法。
XML(Extensible Markup Language)可擴(kuò)展標(biāo)記語言,本身就被設(shè)計(jì)用來存儲(chǔ)數(shù)據(jù),任何一個(gè)對(duì)象都可以用XML來描述。以Team類為例:
- <?xml version="1.0" encoding="utf-8"?>
- <Team xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <Name>Development</Name>
- <Members>
- <Member>
- <Num>001</Num>
- <Name>Marry</Name>
- </Member>
- <Member>
- <Num>002</Num>
- <Name>John</Name>
- </Member>
- </Members>
- </Team>
這樣一個(gè)XML文檔就表示了Team一個(gè)實(shí)例。
聰明的看官應(yīng)該已經(jīng)想到,XML是可以作為對(duì)象信息的載體在網(wǎng)絡(luò)中傳輸,因?yàn)樗俏谋拘问降摹?/p>
怎么進(jìn)行XML文檔與對(duì)象的相互轉(zhuǎn)換呢?
XmlSerializer類就是干這個(gè)活的。
命名空間:System.Xml.Serialization
程序集:System.Xml(在 system.xml.dll 中)
現(xiàn)在這里展示了一個(gè)提供序列化與反序列化方法的EncodeHelper類。
Deserialize方法將XML字符串轉(zhuǎn)換為指定類型的對(duì)象;
Serialize方法則將對(duì)象轉(zhuǎn)換為XML字符串。
- /// <summary>
- /// 提供xml文檔序列化 反序列化
- /// </summary>
- public sealed class EncodeHelper
- {
- /// <summary>
- /// 反序列化XML字符串為指定類型
- /// </summary>
- public static object Deserialize(string Xml, Type ThisType)
- {
- XmlSerializer xmlSerializer = new XmlSerializer(ThisType);
- object result;
- try
- {
- using (StringReader stringReader = new StringReader(Xml))
- {
- result = xmlSerializer.Deserialize(stringReader);
- }
- }
- catch (Exception innerException)
- {
- bool flag = false;
- if (Xml != null)
- {
- if (Xml.StartsWith(Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble())))
- {
- flag = true;
- }
- }
- throw new ApplicationException(string.Format("Couldn't parse XML: '{0}'; Contains BOM: {1}; Type: {2}.", Xml, flag, ThisType.FullName), innerException);
- }
- return result;
- }
- /// <summary>
- /// 序列化object對(duì)象為XML字符串
- /// </summary>
- public static string Serialize(object ObjectToSerialize)
- {
- string result = null ;
- try
- {
- XmlSerializer xmlSerializer = new XmlSerializer(ObjectToSerialize.GetType());
- using (MemoryStream memoryStream = new MemoryStream())
- {
- XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, new UTF8Encoding(false));
- xmlTextWriter.Formatting = Formatting.Indented;
- xmlSerializer.Serialize(xmlTextWriter, ObjectToSerialize);
- xmlTextWriter.Flush();
- xmlTextWriter.Close();
- UTF8Encoding uTF8Encoding = new UTF8Encoding(false, true);
- result= uTF8Encoding.GetString(memoryStream.ToArray());
- }
- }
- catch (Exception innerException)
- {
- throw new ApplicationException("Couldn't Serialize Object:" + ObjectToSerialize.GetType().Name, innerException);
- }
- return result;
- }
- }
要使用這個(gè)類需要添加以下引用
- using System;
- using System.Text;
- using System.IO;
- using System.Xml;
- using System.Xml.Serialization;
下面我們用一個(gè)控制臺(tái)程序來演示一下這個(gè)類是如何工作的。這里是程序的Main函數(shù)。
- static void Main(string[] args)
- {
- List<Member> Members = new List<Member>();
- Member member1 = new Member { Name = "Marry", Num = "001" };
- Member member2 = new Member { Name = "John", Num = "002" };
- Members.Add(member1);
- Members.Add(member2);
- Team team = new Team { Name = "Development", MembersMembers = Members };
- var xml =EncodeHelper.Serialize(team);//序列化
- Console.Write(xml);//打印序列化后的XML字符串
- Console.ReadLine();
- Team newTeam = EncodeHelper.Deserialize(xml, typeof(Team)) as Team;//反序列化時(shí)需要顯式的進(jìn)行類型轉(zhuǎn)換
- Console.WriteLine("Team Name:"+newTeam.Name);//顯示反序列化后的newTeam對(duì)象
- foreach (var member in newTeam.Members)
- {
- Console.WriteLine("Member Num:" + member.Num);
- Console.WriteLine("Member Name:" + member.Name);
- }
- Console.ReadLine();
- }
在執(zhí)行完Console.Write(xml)這行代碼后,就可以看到打印出來的XML文檔了。
- <?xml version="1.0" encoding="utf-8"?>
- <Team xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <Name>Development</Name>
- <Members>
- <Member>
- <Num>001</Num>
- <Name>Marry</Name>
- </Member>
- <Member>
- <Num>002</Num>
- <Name>John</Name>
- </Member>
- </Members>
- </Team>
與我在文章開頭給出的例子是一模一樣的。
最終反序列化出來的newTeam對(duì)象打印出來是這樣的結(jié)果。
Team Name:Development
Member Num:001
Member Name:Marry
Member Num:002
Member Name:John
回到我們開頭的Web通信的例子,
利用XML序列化與反序列化來進(jìn)行對(duì)象傳遞,我們只需要把需要傳遞的對(duì)象序列化為XML字符串,使用一個(gè)隱藏域進(jìn)行form提交就可以搞定咯!
接收方再將接收到的XML字符串反序列化成預(yù)設(shè)的對(duì)象即可。前提是雙方必須約定序列化與反序列化的過程一致,且對(duì)象相同。
最后我們來看一下怎么利用一些特性來控制序列化與反序列化操作的過程。我們把開始的類改一下:
- public class Member
- {
- [XmlElement("Member_Num")]
- public string Num { get; set; }
- public string Name { get; set; }
- }
- [XmlRoot("Our_Team")]
- public class Team
- {
- [NonSerialized]public string Name;修正于2012-4-13
- [XmlIgnore]public string Name;
- public List<Member> Members { get; set; }
- }
- public class Member
- {
- [XmlElement("Member_Num")]
- public string Num { get; set; }
- public string Name { get; set; }
- }
- [XmlRoot("Our_Team")]
- public class Team
- {
- [NonSerialized]public string Name;修正于2012-4-13
- [XmlIgnore]public string Name;
- public List<Member> Members { get; set; }
- }
然后我們?cè)俅螆?zhí)行剛才的控制臺(tái)程序,序列化結(jié)果變成了這樣:
- <?xml version="1.0" encoding="utf-8"?>
- <Our_Team xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <Name>Development</Name>修正于2012-4-13
- <Members>
- <Member>
- <Member_Num>001</Member_Num>
- <Name>Marry</Name>
- </Member>
- <Member>
- <Member_Num>002</Member_Num>
- <Name>John</Name>
- </Member>
- </Members>
- </Our_Team>
本來的根節(jié)點(diǎn)Team變成了Our_Team,Member的子節(jié)點(diǎn)Num變成了Member_Num,并且Team的Name子節(jié)點(diǎn)被忽略了。
可見特性XmlRoot可以控制根節(jié)點(diǎn)的顯示和操作過程,XmlElement則針對(duì)子節(jié)點(diǎn)。如果某些成員被標(biāo)記XmlIgnore NonSerialized修正于2012-4-13特性,則在序列化與反序列化過程中會(huì)被忽略
原文鏈接:http://www.cnblogs.com/John-Connor/archive/2012/04/12/2440352.html
【編輯推薦】