前一段時間因為頻繁使用類的序列化,所以一直在思考如何能更方便的使用這個功能,現在把一段時間的學習過程和大家分享,同時還有個疑問向大家請教,如果您已經非常熟悉類的序列化,那麼請您直接看第三部分。
什麼是類的序列化?說白了,就是把乙個類的例項轉化成一段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中。
以上便是序列化的基本方法,可以滿足我們的需求。但問題是如果我們經常需要對數個類進行序列化和反序列化,就要頻繁的重複上述**,能不能讓類具備自己進行序列化的方法呢?
一、第一次嘗試
我首先想到,可以寫乙個基類,提供進行序列化的方法,任何想實現序列化的類,只需要繼承此類就可以具備此方法。於是構造抽象類:
1public
abstract
class
serializablebaseclass 2
13}
上面一段**和之前的**只有兩行不一樣:
差異1:
cls.gettype()變成gettype():其中gettype()是獲取當前例項的型別,在基類中呼叫gettype()得到的是當前例項的型別,而不是積累的型別。也就是說上述基類中呼叫gettype()不會得到」 serializablebaseclass」,更不會是」system.object」,而是當前物件例項的型別。
差異2:
cls變成this:同理,this引用是指向當前例項的,只不過在基類中,不能使用this直接訪問子類成員。當然通過型別轉換可以達到此目的,但不在本文討論範圍內。所以serialize(stream,this)會將整個物件序列化,而不會造成物件分割,只把基類給序列化了。
二、第二次嘗試
到此為止,任何類只要整合了serializablebaseclass就擁有了自我序列化的方法,但如何反序列化呢?我們在serializablebaseclass類中再新增乙個方法。
1public
object
deserialize(
string
xmlstring)
2此方法就實現了類的反序列化,我們可以這樣使用:
宣告:[serializable]
public class myclass : serializablebaseclass
使用:1
myclass cls
=new
myclass();
2string
xml
=cls. serialize();
3myclass cls1
=(myclass)cls. deserialize(xml);
這個使用乍一看沒什麼問題,但實際使用起來就很蹩腳
1、要想反序列化乙個類,先要建立這個類的例項,只為了呼叫deserialize()
2、呼叫deserialize()返回的是object型別,需要進行型別轉換
對於這兩個問題,我也考慮過很久,如果把deserialize()定義為static,那麼就不能使用gettype()方法,而其,也無法獲取子類的型別。
三、最後的嘗試
對於上述兩個問題,想了很久,始終沒想到解決辦法,直到一天和朋友討論c++stl的某個問題的時候,終於茅塞頓開,c#也是支援模板的呀,於是激動不已,改寫serializablebaseclass類:
1[serializable()]
2public
abstract
class
serializablebaseclass
<
t>3
1415
public
static
t deserialize(
string
xmlstring) 16
23}
24這樣,問題就不完美的解決了(確實不完美)。為什麼不完美呢?那就看下面的**:
[serializable]
public class myclass : serializablebaseclass
使用:myclass cls = myclass.deserialize(xmldata);
看似上述問題都解決了,但我還是心裡不爽,因為每次定義乙個繼承serializablebaseclass的類,還必須把自己的類名再寫一遍,放在模板型別的引數裡。有沒有一種方案,可以讓上述myclass類的宣告預設模板引數就是自身myclass,而無須再寫一遍呢?或者還有更好的其他方法?歡迎討論。
c 中類的序列化 一般化解決方法及最後的疑問
前一段時間因為頻繁使用類的序列化,所以一直在思考如何能更方便的使用這個功能,現在把一段時間的學習過程和大家分享,同時還有個疑問向大家請教,如果您已經非常熟悉類的序列化,那麼請您直接看第三部分。什麼是類的序列化?說白了,就是把乙個類的例項轉化成一段xml格式或二進位制格式的資料,以便於網路傳輸 儲存等...
C 中類的序列化和反序列化
說明 本文演示將類序列化後寫入記事本並從記事本讀取反序列化為物件 1.首先建立乙個類,同時類必須標識為serializable,如下 serializable public class region public string region id public string region name ...
C 中關於類的序列化
1.什麼是序列化 序列化是將物件狀態轉換為可保持或傳輸的格式的過程,在序列化過程中,物件的公共欄位和私有字段以及類的名稱 包括包含該類的程式集 都被轉換為位元組流,然後寫入資料流。與序列化相對的是反序列化,它將流轉換為物件。這兩個過程結合起來,可以輕鬆地儲存和傳輸資料。2.為什麼使用序列化 乙個原因...