日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于对象的序列化

發(fā)布時(shí)間:2024/9/20 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于对象的序列化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Serialization是.NET中一種實(shí)現(xiàn)對(duì)象持久性(Persistent)的機(jī)制。它是一個(gè)將對(duì)象中的數(shù)據(jù)轉(zhuǎn)換成一個(gè)單一元素(通常是Stream)的過程。它的逆過程是Deserialization。Serialization的核心概念是將一個(gè)對(duì)象的所有數(shù)據(jù)看作一個(gè)獨(dú)立的單元。
一般說來,在兩種情況下非常需要Serialization:1)當(dāng)我們希望能夠?qū)?duì)象當(dāng)前的狀態(tài)完整地保存到存儲(chǔ)介質(zhì)中,以便我們以后能夠精確地還原對(duì)象時(shí);2)當(dāng)我們希望將對(duì)象從一個(gè)應(yīng)用程序空間(Application domain)傳遞到另一個(gè)應(yīng)用程序空間時(shí)。例如,Windows Form程序就是利用Serialization機(jī)制來實(shí)現(xiàn)剪貼板的copy & paste的。
.NET Framework支持兩種類型的Serialization:Shallow Serialization和Deep Serialization。
所謂Shallow Serialization是將對(duì)象的可讀寫(read-write)屬性的值轉(zhuǎn)換成字節(jié)流,而對(duì)象內(nèi)部的數(shù)據(jù)(沒有通過read-write屬性暴露出來的數(shù)據(jù))則不被轉(zhuǎn)換。XmlSerializer以及Web Services就使用這種技術(shù)。
Deep Serialization比Shallow Serialization更加徹底,因?yàn)樗菍⒋鎯?chǔ)在對(duì)象私有變量里的實(shí)際值拷貝到字節(jié)流里。而且Deep Serialization還將serialize整個(gè)object graph。也就是說,如果你的對(duì)象持有其他對(duì)象的引用,或者其他對(duì)象引用的集合,那么所有這些對(duì)象都將被Serialize。BinaryFormatter和SoapFormatter以及.NET Remoting都使用Deep Serialization技術(shù),它甚至被有限地用于LosFormatter來產(chǎn)生存儲(chǔ)在Web Form頁中的狀態(tài)數(shù)據(jù)。
本文將著重于Deep Serialization。Serialization的過程
.NET Framework通過Reflection提供自動(dòng)Serialization的機(jī)制。當(dāng)一個(gè)對(duì)象被序列化(Serialized)的時(shí)候,它的類名,Assembly,以及類實(shí)例的所有數(shù)據(jù)成員都將被寫入存儲(chǔ)介質(zhì)中。Serialization引擎保持對(duì)所有已經(jīng)被序列化的對(duì)象引用的追蹤,以確保相同的對(duì)象引用最多只被序列化一次。
通常,一個(gè)Serialization過程會(huì)由formatter(例如BinaryFormatter)的Serialize方法引發(fā)。對(duì)象的Serialization過程按照以下規(guī)則進(jìn)行:
1、?? 檢測(cè)以確保formatter是否擁有一個(gè)代理選擇器(surrogate selector)。如果有,檢查代理選擇器是否持有給定的對(duì)象類型。如果有,ISerializable.GetObjectData被調(diào)用。
2、?? 如果formatter沒有代理選擇器,或者代理選擇器沒有對(duì)象類型,檢查對(duì)象是否被用Serializable屬性標(biāo)記。如果沒有,則拋出SerializationException異常。
3、?? 如果對(duì)象被標(biāo)記為Serializable,檢查對(duì)象是否實(shí)現(xiàn)了ISerializable接口。如果實(shí)現(xiàn)了此接口,則GetObjectData被調(diào)用。
4、?? 如果對(duì)象沒有實(shí)現(xiàn)ISerializable接口,則使用默認(rèn)的序列化策略,來序列化沒有用NonSerialized屬性標(biāo)記的域。使你的class能夠被序列化
通過上面對(duì)Serialization過程的分析,我們可以看出,有兩種方式可以使一個(gè)class能夠被序列化:1)將此class簡(jiǎn)單地標(biāo)記為Serializable;2)為此class實(shí)現(xiàn)ISerializable接口,并將此class標(biāo)記為Serializable。1、?? 標(biāo)記Serializable屬性
標(biāo)記Serializable屬性的方式是實(shí)現(xiàn)Serialization的基本方法。舉個(gè)簡(jiǎn)單的例子:
????[Serializable]
????public class Person
????{
????????public string name = null;
????????public int age = 0;
????}
你可以使用BinaryFormatter來將上面的class序列化:
????????Person sam = new Person();
????????sam.name = "sam";
????????sam.age = 24;
????????IFormatter formatter = new BinaryFormatter();
????????Stream stream = new FileStream("sam.dat",
????????????????????FileMode.Create, FileAccess.Write, FileShare.None);
????????formatter.Serialize(stream, sam);
????????stream.Close();
就是這么簡(jiǎn)單,你所要做的就是創(chuàng)建一個(gè)Stream和一個(gè)formatter的實(shí)例,然后調(diào)用formatter的Serialize方法。經(jīng)過BinaryFormatter serialize的數(shù)據(jù)仍然能夠通過BinaryFormatter deserialize回來,方法與serialize同樣簡(jiǎn)單,這里就不贅述了。
如果你不想將類里的所有域都序列化,可以使用NonSerialized屬性進(jìn)行選擇。如:
????[Serializable]
????public class Person
????{
????????public string name = null;
????????[NonSerialized]
????????public int age = 0;
????}
這樣,age域就不會(huì)被序列化了。
需要注意的是,Serializable屬性并不能被繼承。也就是說如果你希望Person的派生類也能夠被Serialize的話,那么這個(gè)派生類也必須被Serializable標(biāo)記。否則將得到SerializationException異常。
同樣的,Person類中的所有對(duì)其他類的引用,其所引用的類都應(yīng)該是能夠被Serialize的。.NET Framework中的大部分class都實(shí)現(xiàn)了ISerializable接口,但有些class沒有實(shí)現(xiàn),例如ImageList。可以通過MSDN Library的到一個(gè)實(shí)現(xiàn)了ISerializable接口的class列表。對(duì)那些沒有實(shí)現(xiàn)此接口的class,使用的時(shí)候要當(dāng)心。2、?? 實(shí)現(xiàn)ISerializable接口
Serializable屬性的功能非常強(qiáng)大,它使得Serialize和Deserialize變得十分簡(jiǎn)單。但凡事有利必有弊,由Serializable實(shí)現(xiàn)的自動(dòng)序列化方法有時(shí)不夠靈活。我們并不能完全控制Serialize和Deserialize的行為,而有些時(shí)候它們的行為對(duì)我們來說很重要。那么我們通過何種方法能夠控制Serialize和Deserialize的行為呢?答案就是,自己來實(shí)現(xiàn)ISerializable接口。ISerializable接口給予我們更大的自由來控制Serialize和Deserialize,但是無疑我們將不得不寫更多的代碼L。
下面我們來看看如何實(shí)現(xiàn)ISerializabe接口。ISerializable接口位于System.Runtime.Serialization名字空間中,聲明如下:
public inferface ISerializable?????? {
void GetObjectData(SerializationInfo info,
????????????????????????????StreamingContext context);?????? }
它只有一個(gè)方法GetObjectData。因此,像實(shí)現(xiàn)其他接口一樣,我們必須實(shí)現(xiàn)此方法。但與其他接口不同的是,為了Deserialization,我們還必須實(shí)現(xiàn)一個(gè)特殊的構(gòu)造函數(shù)(我稱此構(gòu)造函數(shù)為“序列化構(gòu)造函數(shù)”),此構(gòu)造函數(shù)具有與GetObjectData相同的參數(shù)列表。由于此構(gòu)造函數(shù)專門用于.NET Framework在Deserialize時(shí)的Reflection機(jī)制,因此我們通常將它聲明為保護(hù)或私有模式。如下:(當(dāng)然,如果你的class只需要Serialize而不需要Deserialize的話,也可以不實(shí)現(xiàn)這個(gè)特殊的構(gòu)造函數(shù))
????[Serializable]
????public class Person : ISerializable
????{
????????public string name = null;
????????public int age = 0;
????????public Person()
????????{
????????}
????????protected Person(SerializationInfo info, StreamingContext context)
????????{
????????????name = info.GetString("name");
????????????age = info.GetInt32("age");
????????}
????????void ISerializable.GetObjectData(SerializationInfo info,
????????????????????????????????????????StreamingContext context)
????????{
????????????info.AddValue("name", name);
????????????info.AddValue("age", age);
????????}
????}
通過實(shí)現(xiàn)ISerializable接口,使得我們有機(jī)會(huì)在ISerializable.GetObjectData中控制Serialize的行為,在“序列化構(gòu)造函數(shù)”中控制Deserialize的行為。這個(gè)接口提供給我們的信息非常全面而靈活,以致于我們甚至可以在這兩個(gè)方法中耍些花招。比如,我們可以在Deserialize的時(shí)候,籍由改變info.FullTypeName來得到一種與被Serialize的對(duì)象不同類型的另一個(gè)對(duì)象等。獨(dú)辟蹊徑
前面談到過Serialization被運(yùn)用的典型環(huán)境,是對(duì)象存儲(chǔ)、進(jìn)程間數(shù)據(jù)傳遞等涉及到對(duì)象持久性的領(lǐng)域。但實(shí)際上,它也能夠被運(yùn)用到其他的許多地方,關(guān)鍵在于我們是否能想到去用運(yùn)Serialization,有時(shí)候思維定式也是很可怕的J。舉個(gè)例子,我們來看看在Clone方法中如何使用Serialization[1]。
如果我們要為Person類實(shí)現(xiàn)Clone方法,我們通常會(huì)這樣寫:
????[Serializable]
????public class Person : ICloneable
????{
????????public string name = null;
????????public int age = 0;
????????public object Clone()
????????{
????????????Person person = new Person();
????????????person.name = name;
????????????person.age = age;
????????????return person;
????????}
????}
如果我們利用Serialization的方法,Clone函數(shù)就能寫成下面的樣子:
????????public object Clone()
????????{
????????????MemoryStream stream = new MemoryStream();
????????????BinaryFormatter formatter = new BinaryFormatter();
????????????formatter.Serialize(stream, this);
????????????stream.Position = 0;
????????????return formatter.Deserialize(stream);
????????}
從這兩個(gè)實(shí)現(xiàn)上看,使用Serialization實(shí)現(xiàn)Clone方法似乎并沒有什么好處。可是設(shè)想如果你面對(duì)的是一個(gè)復(fù)雜的類繼承體系,從基類到派生類都需要實(shí)現(xiàn)Clone方法。利用第一種實(shí)作手法,你將不得不為每一個(gè)class寫一個(gè)Clone方法,而且隨著數(shù)據(jù)成員的增多,這個(gè)方法將越來越冗長(zhǎng),并且會(huì)由于數(shù)據(jù)成員的改變而引發(fā)錯(cuò)誤(我曾經(jīng)遇到過好幾次,由于class中增加了成員變量,而Clone方法沒有及時(shí)更新,導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。呵呵,這種錯(cuò)誤還很難調(diào)試)。現(xiàn)在你看到用Serialization實(shí)現(xiàn)的好處了吧?是的,我們只要在基類中將Clone方法聲明為virtual,并用Serialization的方法實(shí)現(xiàn)之,然后保證基類和派生類都可以被Serialize,上面所有的麻煩不都迎刃而解了嗎?總結(jié)
現(xiàn)代軟件項(xiàng)目中,無論何種項(xiàng)目都會(huì)或多或少地涉及到對(duì)象持久性的問題,.NET也不例外,無論是Windows Form、ASP.NET,還是Web Services,都需要處理對(duì)象持久性。而Serialization正是.NET為應(yīng)對(duì)這個(gè)問題而給出的解法。

總結(jié)

以上是生活随笔為你收集整理的关于对象的序列化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。