上篇總結了下JSON的序列化和反序列化,博園中大牛給了很多牛叉的評論,學習了不少。
不過在上篇中忘了把json序列化和反序列化的另外一種方式寫上去了,這里做個簡單的補充:
Json篇:http://www.cnblogs.com/zhanghaomars/p/3557644.html
Json序列化和反序列化擴展方法實現類:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Script.Serialization; namespace HelpClass.TypeHelp { public static class JsonHelpExpand { public static string JsonSerializer<T>(this T t) where T : class { JavaScriptSerializer jsonSerialize = new JavaScriptSerializer(); return jsonSerialize.Serialize(t); } public static T JsonDeserialize<T>(this string jsonString) { JavaScriptSerializer jsonSerialize = new JavaScriptSerializer(); return (T)jsonSerialize.Deserialize<T>(jsonString); } } }
Ok!接下來就是XML
1、 靜態方法+泛型實現
XML工具類:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml; using System.Xml.Serialization; namespace HelpClass.TypeHelp { public class XMLHelp { private static void XmlSerializeInternal(Stream stream, object o, Encoding encoding, bool isnamespaces) { if (o == null) throw new ArgumentNullException("o"); if (encoding == null) throw new ArgumentNullException("encoding"); XmlSerializer serializer = new XmlSerializer(o.GetType()); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.NewLineChars = "\r\n"; settings.Encoding = encoding; settings.IndentChars = " "; //不生成聲明頭 settings.OmitXmlDeclaration = !isnamespaces; MemoryStream w = new MemoryStream(); XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); namespaces.Add("", ""); using (XmlWriter writer = XmlWriter.Create(stream, settings)) { serializer.Serialize(writer, o, namespaces); writer.Close(); } } /// <summary> /// 將一個對象序列化為XML字符串 /// </summary> /// <param name="o">要序列化的對象</param> /// <param name="encoding">編碼方式</param> /// <param name="isnamespaces">是否需要命名空間true:需要 false:不需要</param> /// <returns>序列化產生的XML字符串</returns> public static string XmlSerialize(object o, Encoding encoding, bool isnamespaces) { using (MemoryStream stream = new MemoryStream()) { XmlSerializeInternal(stream, o, encoding, isnamespaces); stream.Position = 0; using (StreamReader reader = new StreamReader(stream, encoding)) { return reader.ReadToEnd(); } } } /// <summary> /// 從XML字符串中反序列化對象 /// </summary> /// <typeparam name="T">結果對象類型</typeparam> /// <param name="s">包含對象的XML字符串</param> /// <param name="encoding">編碼方式</param> /// <returns>反序列化得到的對象</returns> public static T XmlDeserialize<T>(string s, Encoding encoding) { if (string.IsNullOrEmpty(s)) throw new ArgumentNullException("s"); if (encoding == null) throw new ArgumentNullException("encoding"); XmlSerializer mySerializer = new XmlSerializer(typeof(T)); using (MemoryStream ms = new MemoryStream(encoding.GetBytes(s))) { using (StreamReader sr = new StreamReader(ms, encoding)) { return (T)mySerializer.Deserialize(sr); } } } /// <summary> /// 將一個對象按XML序列化的方式寫入到一個文件 /// </summary> /// <param name="o">要序列化的對象</param> /// <param name="path">保存文件路徑</param> /// <param name="encoding">編碼方式</param> /// <param name="isnamespaces">是否需要命名空間true:需要 false:不需要</param> public static void XmlSerializeToFile(object o, string path, Encoding encoding, bool isnamespaces) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); using (FileStream file = new FileStream(path, FileMode.Create, FileAccess.Write)) { XmlSerializeInternal(file, o, encoding,isnamespaces); } } /// <summary> /// 讀入一個文件,並按XML的方式反序列化對象。 /// </summary> /// <typeparam name="T">結果對象類型</typeparam> /// <param name="path">文件路徑</param> /// <param name="encoding">編碼方式</param> /// <returns>反序列化得到的對象</returns> public static T XmlDeserializeFromFile<T>(string path, Encoding encoding) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); if (encoding == null) throw new ArgumentNullException("encoding"); string xml = File.ReadAllText(path, encoding); return XmlDeserialize<T>(xml, encoding); } } }
在一個項目中,如果面臨大量的XML(如調用大量返回XML的外部接口),這時就需要根據XML結構來逆向推導C#類型,然后才能使用序列化和反序列化的方法。
當需要根據XML結構逆向推導類型,我們需要了解一下類型定義與XML結構的映射關系。
映射關系只需要記住幾個標簽:
(1) [XmlElement]
類中的屬性或者字段在不標記下默認都會生成XmlElement(不加任何Attribute的情況下)該標簽把類中的屬性或者字段序列化為XML中的節點
Public class ddd
{
[XmlElement]
Public string d1{get;set;}
Public string d2{get;set;}
}
ddd cd=new ddd{d1=”1”,d2=”2”}
<ddd><d1>1</d1><d2>2</d2></ddd>
(2) [XmlAttribute]
類中的屬性或者字段在標記為[XmlAttribute]的情況下會生成為XML中以以該類名為節點的屬性
Public class ddd
{
[XmlAttribute]
Public string d1{get;set;}
[XmlElement]
Public string d2{get;set;}
}
ddd cd=new ddd{d1=”1”,d2=”2”}
<ddd d1=”1”><d2>2</d2></ddd>
(3) [InnerText]
如果希望類型中的屬性或者字段生成InnerText,需要在類型的成員上用[XmlText]
Public class ddd
{
[XmlAttribute]
Public string d1{get;set;}
[InnerText]
Public string d2{get;set;}
}
ddd cd=new ddd{d1=”1”,d2=”2”}
<ddd d1=”1”>2</ddd>
(4) 重命名
XmlAttribute,XmlElement允許接受一個別名用來控制生成節點的名稱,類型的重命名用XmlType來實現
[XmlType(“ccc”)]
Public class ddd
{
[XmlAttribute(“c1”)]
Public string d1{get;set;}
[XmlElement(“c2”)]
Public string d2{get;set;}
}
ddd cd=new ddd{d1=”1”,d2=”2”}
<ccc c1=”1”><c2>2</c2></ccc>
(5) 序列化去掉XML命名空間及聲明頭(工具類中代碼以有相關說明了)
注意:
(1) 當需要考慮使用XML時,先不要想着XML結構,先應該定義好數據類型。
(2) 列表節點不要使用[XmlElement],它會讓所有子節點【升級】,顯得結構混亂。
(3) 如果希望序列化的XML長度小一點,可以采用[XmlAttribute],或者指定一個更短小的別名(序列化為JSON進行傳輸也是一種選擇)
(4) 不要在一個列表中輸出不同的數據類型,這樣的XML結構的可讀性不好。
(5) 盡量使用UTF-8編碼,不要使用GB2312編碼。
(6) 列表節點不要使用[XmlElement],它會讓所有子節點【升級】,顯得結構混亂。
2、 擴展方法+泛型實現
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml; using System.Xml.Serialization; namespace HelpClass.TypeHelp { public static class XMLHelpExpand { /// <summary> /// XML序列化 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="o"></param> /// <param name="isnamespaces">是否需要命名空間true:需要 false:不需要</param> /// <returns></returns> public static string XmlSerializer<T>(this T o,bool isnamespaces)where T:class { System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(o.GetType()); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.NewLineChars = "\r\n"; settings.Encoding = Encoding.UTF8; settings.IndentChars = " "; //不生成聲明頭 settings.OmitXmlDeclaration = !isnamespaces; MemoryStream w = new MemoryStream(); XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); namespaces.Add("", ""); using (XmlWriter writer = XmlWriter.Create(w, settings)) { serializer.Serialize(writer, o, namespaces); writer.Close(); } return Encoding.UTF8.GetString(w.ToArray()); } /// <summary> /// XML反序列化 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="XmlString"></param> /// <returns></returns> public static T XmlDeserialize<T>(this string XmlString) { if (string.IsNullOrEmpty(XmlString)) throw new ArgumentNullException("s"); XmlSerializer mySerializer = new XmlSerializer(typeof(T)); using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XmlString))) { using (StreamReader sr = new StreamReader(ms, Encoding.UTF8)) { return (T)mySerializer.Deserialize(sr); } } } } }
看完了上面的這些或許你已經對XML的序列化和反序列化有了一定的了解,今天就寫到這里,下次總結一下別的。