詳解 C# 中XML對象的序列化和反序列化

這一篇主要是用來介紹關於C#中的XML序列化的問題,這個相信大傢一定會經常使用它,特別是在WPF中,有時候我們需要將我們後臺的數據保存在數據庫中,從而在軟件下一次啟動的時候能夠自動去加載這些數據,由於我們的這些Model中字段眾多,如果單獨進行保存那是不太現實的,這個時候將這些字段序列化成xml字符串並保存在數據庫中就是一個不錯的選擇,當我們需要這些數據的時候我們也可以反過來將其序列化為一些字段,最終達到我們的效果,首先我們來看看是如何實現的?

public class XMLUtil
{
    /// <summary>
    /// XML & Datacontract Serialize & Deserialize Helper
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="serialObject"></param>
    /// <returns></returns>
    public static string Serializer<T>(T serialObject) where T : class
    {
        try
        {
            XmlSerializer ser = new XmlSerializer(typeof(T));
            System.IO.MemoryStream mem = new MemoryStream();
            XmlTextWriter writer = new XmlTextWriter(mem, Encoding.UTF8);
            ser.Serialize(writer, serialObject);
            writer.Close();
 
            return Encoding.UTF8.GetString(mem.ToArray());
        }
        catch (Exception ex)
        {
            return null;
        }
    }
 
    public static T Deserialize<T>(string str) where T : class
    {
        try
        {
            XmlSerializer mySerializer = new XmlSerializer(typeof(T));
            StreamReader mem2 = new StreamReader(
                    new MemoryStream(System.Text.Encoding.UTF8.GetBytes(str)),
                    System.Text.Encoding.UTF8);
 
            return (T)mySerializer.Deserialize(mem2);
        }
        catch (Exception)
        {
            return null;
        }
    }
    
}

  微軟為我們提供的XmlSerializer這個類就為我們提供瞭這個可能,在序列化的過程中我們需要註意下面的情況,所有的屬性必須是可序列化的對象,像BitmapImage、SolidColorBrush等這些對象都是不能夠進行序列化的對象,如果用上面的方法進行序列化時將返回null,正確的方式是在這些字段上面加上[XmlIgnore]說明,從而在進行序列化時候跳過這些對象,就像下面的方式。

/// <summary>
///背景顏色
/// </summary>
private SolidColorBrush _BackgroundColor;
[XmlIgnore]
public SolidColorBrush BackgroundColor
{
    get
    {
        return _BackgroundColor;
    }
    set
    {
        if (value != _BackgroundColor)
        {
            _BackgroundColor = value;
            OnPropertyChanged("BackgroundColor");
        }
    }
}

  那麼像上面的這個SolidColorBrush對象該怎樣去進行序列化呢,這裡我們選擇將當前顏色的ARGB值保存在一個byte數組中,從而在反序列化的時候通過Color.FromArgb的方式進行還原,就像下面的方式。

byte[] colorByte=savedModel.ConfigurationBaseModel.BackgroundColorArgb;
    Color backColor=Color.FromArgb(colorByte[0],colorByte[1],colorByte[2],colorByte[3]);
    sourceBaseModel.BackgroundColor = new SolidColorBrush(backColor);

  那麼這個對象在進行序列化的時候該怎麼進行保存呢?同樣的原理我們可以通過下面的方式。

/// <summary>
///背景顏色
/// </summary>
private SolidColorBrush _BackgroundColor;
[XmlIgnore]
public SolidColorBrush BackgroundColor
{
    get
    {
        return _BackgroundColor;
    }
    set
    {
        if (value != _BackgroundColor)
        {
            _BackgroundColor = value;
            OnPropertyChanged("BackgroundColor");
        }
    }
}
 
/// <summary>
///背景顏色ARGB
/// </summary>
private byte[] _BackgroundColorArgb=new byte[4];
[XmlArray("argb"),XmlArrayItem("value")]
public byte[] BackgroundColorArgb
{
    get
    {
        if (null != _BackgroundColor)
        {
            Color color = _BackgroundColor.Color;
            _BackgroundColorArgb[0] = color.A;
            _BackgroundColorArgb[1] = color.R;
            _BackgroundColorArgb[2] = color.G;
            _BackgroundColorArgb[3] = color.B;
        }
        return _BackgroundColorArgb;
    }
    set
    {
        if (value != _BackgroundColorArgb)
        {
            _BackgroundColorArgb = value;
            OnPropertyChanged("BackgroundColorArgb");
        }
     
    }
}

  這裡在實際的使用中發現,就像byte數組必須通過[XmlArray(“argb”),XmlArrayItem(“value”)] 這類型的標識來將其分類,在將其序列化完畢以後,我們可以看看這個BackgroundColorArgb字段最終是通過怎樣的方式來保存的?   

    在進行反序列化的時候會將這個argb和value反序列化為一個byte數組。

    除瞭這些特例意外,有時候經常需要將一些對象的數組進行序列化,那麼原理是什麼呢?這裡我借用別人的一個例子來進行相關的說明。

 對象數組的Xml序列化:

 數組的Xml序列化需要使用XmlArrayAttribute和XmlArrayItemAttribute;XmlArrayAttribute指定數組元素的Xml節點名,XmlArrayItemAttribute指定數組元素的Xml節點名。

 如下代碼示例: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
  
namespace UseXmlSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            //聲明一個貓咪對象
            var cWhite = new Cat { Color = "White", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat" };
            var cBlack = new Cat { Color = "Black", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat" };
  
            CatCollection cc = new CatCollection { Cats = new Cat[] { cWhite,cBlack} };
  
            //序列化這個對象
            XmlSerializer serializer = new XmlSerializer(typeof(CatCollection));
  
            //將對象序列化輸出到控制臺
            serializer.Serialize(Console.Out, cc);
  
            Console.Read();
        }
    }
  
    [XmlRoot("cats")]
    public class CatCollection
    {
        [XmlArray("items"),XmlArrayItem("item")]
        public Cat[] Cats { get; set; }
    }
  
    [XmlRoot("cat")]
    public class Cat
    {
        //定義Color屬性的序列化為cat節點的屬性
        [XmlAttribute("color")]
        public string Color { get; set; }
  
        //要求不序列化Speed屬性
        [XmlIgnore]
        public int Speed { get; set; }
  
        //設置Saying屬性序列化為Xml子元素
        [XmlElement("saying")]
        public string Saying { get; set; }
    }
}

  最終獲得的結果是:  

<?xml version="1.0" encoding="gb2312"?>
<cats xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <items>
    <item color="White">
      <saying>White or black,  so long as the cat can catch mice,  it is a good cat</saying>
    </item>
    <item color="Black">
      <saying>White or black,  so long as the cat can catch mice,  it is a good cat</saying>
    </item>
  </items>
</cats> 

以上就是詳解 C# 中XML對象的序列化和反序列化的詳細內容,更多關於c# xml序列化和反序列化的資料請關註WalkonNet其它相關文章!

推薦閱讀: