c#中類的序列化:一般化解決方案及最後的疑問

來源:互聯網
上載者:User

前一段時間因為頻繁使用類的序列化,所以一直在思考如何能更方便的使用這個功能,現在把一段時間的學習過程和大家分享,同時還有個疑問向大家請教,如果您已經非常熟悉類的序列化,那麼請您直接看第三部分。

什麼是類的序列化?說白了,就是把一個類的執行個體轉化成一段XML格式或二進位格式的資料,以便於網路傳輸、儲存等操作。
同理,還原序列化就是把XML或者二進位描述的對象還原成一個類的執行個體。

零、開始序列化
在C#中,要實作類別的序列化並不難,以XML序列化為例,首先我們聲明一個類:
[Serializable]
public class myClass
{
 ......
}
其中類聲明上面的一句[Serializable]用來指示此類是可以序列化的,然後
引用兩個namespace:

using System.IO;
using System.Xml.Serialization;

於是就可以執行下面代碼:

 

1Code
2myClass cls = new myClass();
3XmlSerializer xmlSerializer = new XmlSerializer(cls.GetType());
4MemoryStream stream = new MemoryStream();
5xmlSerializer.Serialize(stream, cls);
6byte[] buf = stream.ToArray();
7string xml = Encoding.ASCII.GetString(buf);
8stream.Close();

自此,序列化就完成了,XML序列儲存在string xml;變數中。
上述代碼不難理解,XmlSerializer類用來提供XML序列化的功能,xmlSerializer.Serialize(stream, cls)方法,可以把類cls序列化,並將XML序列儲存在流stream中。
以上便是序列化的基本方法,可以滿足我們的需求。但問題是如果我們經常需要對數個類進行序列化和還原序列化,就要頻繁的重複上述代碼,能不能讓類具備自己進行序列化的方法呢?

一、第一次嘗試
我首先想到,可以寫一個基類,提供進行序列化的方法,任何想實現序列化的類,只需要繼承此類就可以具備此方法。於是構造抽象類別:

 

 

 1 public abstract class SerializableBaseClass 
 2 { 
 3         public virtual string XMLSerialize() 
 4         { 
 5             XmlSerializer xmlSerializer = new XmlSerializer(GetType()); //差異1 
 6             MemoryStream stream = new MemoryStream(); 
 7             xmlSerializer.Serialize(stream, this); //差異2 
 8             byte[] buf = stream.ToArray(); 
 9             string xml = Encoding.ASCII.GetString(buf); 
10             stream.Close(); 
11             return xml; 
12         } 
13 } 

上面一段代碼和之前的代碼只有兩行不一樣:
差異1:
cls.GetType()變成GetType():其中GetType()是擷取當前執行個體的類型,在基類中調用GetType()得到的是當前執行個體的類型,而不是積累的類型。也就是說上述基類中調用GetType()不會得到” SerializableBaseClass”,更不會是”System.Object”,而是當前對象執行個體的類型。

差異2:
cls變成this:同理,this引用是指向當前執行個體的,只不過在基類中,不能使用this直接存取子類成員。當然通過類型轉換可以達到此目的,但不在本文討論範圍內。所以Serialize(stream,this)會將整個對象序列化,而不會造成對象分割,只把基類給序列化了。

二、第二次嘗試
到此為止,任何類只要整合了SerializableBaseClass就擁有了自我序列化的方法,但如何還原序列化呢?我們在SerializableBaseClass類中再添加一個方法。

 

1 public object DeSerialize(string xmlString)
2 {
3     XmlSerializer xmlSerializer = new XmlSerializer(GetType());
4     byte[] buf = Encoding.ASCII.GetBytes(xmlString);
5     MemoryStream stream = new MemoryStream(buf);
6     object o = xmlSerializer.Deserialize(stream);
7     return o;
8 }

此方法就實現了類的還原序列化,我們可以這樣使用:
聲明:
[Serializable]
public class myClass : SerializableBaseClass
{
 ……
}
使用:

 

1 myClass cls = new myClass();
2 string xml = cls. Serialize();
3 myClass cls1 = (myClass)cls. DeSerialize(xml);

 

這個使用乍一看沒什麼問題,但實際使用起來就很蹩腳
1、要想還原序列化一個類,先要建立這個類的執行個體,只為了調用DeSerialize()
2、調用DeSerialize()返回的是object類型,需要進行類型轉換

對於這兩個問題,我也考慮過很久,如果把DeSerialize()定義為static,那麼就不能使用GetType()方法,而其,也無法擷取子類的類型。

三、最後的嘗試
對於上述兩個問題,想了很久,始終沒想到解決辦法,直到一天和朋友討論c++STL的某個問題的時候,終於茅塞頓開,c#也是支援模板的呀,於是激動不已,改寫SerializableBaseClass類:

 

 1 [Serializable()] 
 2 public abstract class SerializableBaseClass <T> 
 3 { 
 4     public virtual string XMLSerialize() 
 5     { 
 6         XmlSerializer xmlSerializer = new XmlSerializer(GetType()); 
 7         MemoryStream stream = new MemoryStream(); 
 8         xmlSerializer.Serialize(stream, this); 
 9         byte[] buf = stream.ToArray(); 
10         string xml = Encoding.ASCII.GetString(buf); 
11         stream.Close(); 
12         return xml; 
13 } 
14 
15 public static T DeSerialize(string xmlString) 
16     { 
17         XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); 
18         byte[] buf = Encoding.ASCII.GetBytes(xmlString); 
19         MemoryStream stream = new MemoryStream(buf); 
20         T o = (T)xmlSerializer.Deserialize(stream); 
21         return o; 
22     } 
23 } 
24 

 

這樣,問題就不完美的解決了(確實不完美)。為什麼不完美呢?那就看下面的代碼:
[Serializable]
public class myClass : SerializableBaseClass<myClass>
{
 ……
}
使用:
myClass cls = myClass.DeSerialize(xmlData);
看似上述問題都解決了,但我還是心裡不爽,因為每次定義一個繼承SerializableBaseClass的類,還必須把自己的類名再寫一遍,放在模板類型的參數裡。有沒有一種方案,可以讓上述myClass類的聲明預設範本參數就是自身myClass,而無須再寫一遍<myClass>呢?或者還有更好的其他方法?歡迎討論。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.