1. 程式人生 > 實用技巧 >XmlSerializer 序列化總結

XmlSerializer 序列化總結

序列化反序列化例程 參考微軟官網,所有相關問題理論上都能在裡面找到原因。注意裡面說到XmlSerializer new的時候只有倆種方式才不會發生記憶體洩漏。其餘會出現dll不釋放的記憶體洩漏。

XmlSerializer(Type) 
XmlSerializer.XmlSerializer(Type, String) 

1.節點

碰到的問題,就是1)類節點要重新命名 ,後面找到“XmlTypeAttribute”;2)陣列定義物件不想陣列名佔用節點,找到“XmlElementAttribute”;3)類定義預設節點名稱,使用“XmlTypeAttribute

節點/屬性重新命名,一般方式是 XmlXXXX(XXXXName=“新的節點名”)

節點參考“Tozhang”的部落格

  

XmlElement節點重新命名

XmlRoot 根節點重名稱

XmlArrayList集合新增根節點

XmlArrayItemList集合中子節點重新命名

[Serializable] 將該類標記為可以序列化類
[XmlRoot(“root”)]可以指定重新指定xml根節點的名稱,若不加這特性,此類在序列化時候,會預設使用類名作為根節點

[XmlRootAttribute("Slab", IsNullable = false)]

[XmlElement(“code”)]
[XmlIgnore] 此特性是忽略此屬性
[XmlAttribute(“attr”)] 此屬性會作為特性在 元素中

 
  [XmlTypeAttribute(TypeName = "Segment")] //設定類的節點名稱 是“Segment” public class SegmentXXX {
……
  }

[XmlRootAttribute("MyCity", Namespace="abc.abc", IsNullable=false)] // 當該類為Xml根節點時,以此為根節點名稱。
public class City


[XmlAttribute("AreaName")] // 表現為Xml節點屬性。<... AreaName="..."/>
public string Name


[XmlElementAttribute("AreaId", IsNullable = false)] // 表現為Xml節點。<AreaId>...</AreaId>
public string Id


[XmlArrayAttribute("Areas")] // 表現為Xml層次結構,根為Areas,其所屬的每個該集合節點元素名為類名。<Areas><Area ... /><Area ... /></Areas>
public Area[] Areas


[XmlElementAttribute("Area", IsNullable = false)] // 表現為水平結構的Xml節點。<Area ... /><Area ... />... 對比上面就是少掉“Areas”節點,少一次縮排。
public Area[] Areas


[XmlIgnoreAttribute] // 忽略該元素的序列化。

2.改變XML序列化的預設值

參考“yubinfeng”部落格。部落格描述很詳細,作為第二個示例
遇到問題,要去除開頭的xml語句,並去掉根節點的xml名空間宣告。

/// <summary>
/// 返回去除節點頭部的
/// </summary>
/// <param name="filename"></param>
/// <param name="xtw"></param>
/// <param name="xmlSN"></param>
private void ReturnXmlWrite(string filename, out XmlWriter xtw, out XmlSerializerNamespaces xmlSN)
{
//設定序序化XML格式
MemoryStream ms = new MemoryStream();
XmlWriterSettings xws = new XmlWriterSettings();
xws.Indent = true; //獲取或設定一個值,該值指示是否縮排元素。
xws.OmitXmlDeclaration = true;//獲取或設定一個值,該值指示是否省略XML宣告。
xws.Encoding = System.Text.Encoding.UTF8;//設定編碼,讀取的時候同樣編碼,可以省略xml帶編碼行
xtw = XmlTextWriter.Create(filename, xws);
//去掉要結點的 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 屬性
xmlSN = new XmlSerializerNamespaces();
xmlSN.Add("", "");
}

3.反射錯誤

  執行的時候一直報反射錯誤。查很久,發現是“同名屬性錯誤”

/// <summary>
    /// 平板周長定義,必須。逆時針相對於平板邊界框的左下角給出座標
    /// </summary>
    [XmlTypeAttribute(TypeName = "Zone")]
    public class MainZone
    {
       
        [XmlElement(ElementName = "Zone")]
        public Zone unPickZone;
        public SlabZone()
        {
            segments = new Segment[4];
            for (int i = 0; i < 4; i++)
                segments[i] = new Segment();
            unPickZone = new Zone();
        }
    }
  
上面程式碼在執行 = new
XmlSerializer(Type) 會彈窗報錯。
原因是 "MainZone "關聯的屬性名“Zone” 和 成員物件的類“Zone”衝突。
更改方法:倆個裡面挑一個重新命名為其它。


4. 注意事項

yubinfeng轉載過來。

XML序列化一些注意事項

(1)要序列化的類必須有預設的構造的建構函式,才能使用XmlSerializer序列化,需要序列化的類都必須有一個無參的建構函式(通過對基礎中類和類的例項學習,我們必須知道類不定義建構函式的情況下,會預設生成一個無引數的建構函式);

  補充:如果變數只宣告,沒有賦值,序列化後是沒有對應的節點和屬性值。

(2)索引器、私有欄位或只讀屬性(只讀集合屬性除外)不能被序列化;

(3)不想序列化時:當不想序列化一個屬性時,使用[System.Xml.Serialization.XmlIgnore]標記,能用於屬性;[NonSerializable]應用於屬性無效,能用於類,結構體等;

(4)方法不能被序列化(雖然是廢話,但是還是列舉出來);

(5)列舉變數可序列化為字串,無需用[XmlInclude]

(6)匯出非基本型別物件,都必須用[XmlInclude]事先宣告。該規則遞迴作用到子元素 。可以參考spacer_robot

(7)Attribute中的IsNullable引數若等於false,表示若元素為null則不顯示該元素。(針對值型別有效)

(8)某些類就是無法XML序列化的(即使使用了[XmlInclude])

比如:

IDictionary(如HashTable);

父類物件賦予子類物件值的情況;

物件間迴圈引用;

(9)對於無法XML序列化的物件,可考慮:

使用自定義xml序列化(實現IXmlSerializable介面);

實現IDictionary的類,可考慮(1)用其它集合類替代;(2)用類封裝之,並提供Add和this函式;

某些型別需要先經過轉換,然後才能序列化為XML。如XML序列化System.Drawing.Color,可先用ToArgb()將其轉換為整數;

過於複雜的物件用xml序列化不便的話,可考慮用二進位制序列化;

(10)預設建構函式是必須的,因為反序列化本質上使用的是反射,需要預設建構函式來例項化類,如果去掉其中的預設建構函式,則編譯沒有問題,但執行就會報錯。

儘量不要將比較大的屬性放在預設建構函式初始化,那會導致在反序列化時對列表初始化兩次:預設建構函式中執行一次,反序列化時從XML文件讀取再執行一次。

以上十點注意,其中前三點,也就是加黑的這幾點,是重點要知道的。

5.引用

引用來源:1.https://www.cnblogs.com/yubinfeng/p/4631838.html

     2.https://www.cnblogs.com/zhang1f/p/11666930.html

     3.https://www.cnblogs.com/zsh_robot/articles/1323949.html

     4.https://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html 部落格裡面還有其它方式處理xml

     5.https://docs.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlserializer?view=net-5.0 微軟官方文件