国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

.NET Framework中的串行化操作

2019-11-17 04:42:36
字體:
供稿:網(wǎng)友

  簡介

  .NET中的串行化答應(yīng)編程人員獲得一個對象的實例,并將它轉(zhuǎn)換為一種易于在網(wǎng)絡(luò)上傳播或著在數(shù)據(jù)庫、文件系統(tǒng)上存儲的格式。該對象實際上是一個定制類型(包括我們已經(jīng)設(shè)置的任何屬性或字段)的實例。
我能想到的一些例子包括通過Web服務(wù)等向本地或遠程應(yīng)用程序的另一部分發(fā)送對象實例的能力。選擇串行化的另一個例子是在正常情況下存儲在數(shù)據(jù)庫中的對象的數(shù)據(jù),但數(shù)據(jù)的一部分無需個別地進行存儲。通過只將需要查詢的數(shù)據(jù)列成單獨的字段,數(shù)據(jù)的其余部份可以在一個定制類型內(nèi)進行簡單的串行化,并在數(shù)據(jù)庫中存儲為一個完整的對象。

  下面我們舉一個調(diào)度對象的例子。這一調(diào)度對象能夠使應(yīng)用程序根據(jù)一個特定的進度表觸發(fā)事件。在開發(fā)調(diào)度對象時,需要考慮許多設(shè)置,例如時間間隔、日期和時間限制等。當(dāng)對于下一個事件應(yīng)當(dāng)何時被觸發(fā)真正重要的信息片斷是精確的日期/時間時,正常情況下,數(shù)據(jù)的每個部份都要求在表中創(chuàng)建一個單獨的字段?,F(xiàn)在,我們將整個調(diào)度對象串行化,并與下一次事件發(fā)生的日期/時間一起存儲在數(shù)據(jù)庫中,這樣,使得整個數(shù)據(jù)庫只包含有3個字段。

  本文包含了可以將對象串行化為的二種格式:xml或二進制,其中每種形式都各有優(yōu)缺點。本文還論述了串行化的二種方式:基本串行化和定制串行化。最后,文章將以一個實例演示如何通過互聯(lián)網(wǎng)發(fā)送一個定制對象的例子。

  任何串行化處理的第一步都是獲取對象的實例,并將它轉(zhuǎn)化為一種內(nèi)存流。下面的代碼演示了完成串行化的4個方法:二進制以及XML的串行化、反串行化。在后面的內(nèi)容中,我們將論述二進制、XML串行化的區(qū)別:

Figure 1.1 核心的串行化方法

#region Binary Serializers
public static System.IO.MemoryStream SerializeBinary(object request) {
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
serializer.Serialize(memStream, request);
return memStream;
}

public static object DeSerializeBinary(System.IO.MemoryStream memStream) {
 memStream.Position=0;
 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter deserializer =
      new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
 object newobj = deserializer.Deserialize(memStream);
 memStream.Close();
 return newobj;
}
#endregion

#region XML Serializers

public static System.IO.MemoryStream SerializeSOAP(object request) {

 System.Runtime.Serialization.Formatters.Soap.SoapFormatter serializer =
      new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
 System.IO.MemoryStream memStream = new System.IO.MemoryStream();
 serializer.Serialize(memStream, request);
 return memStream;
}

public static object DeSerializeSOAP(System.IO.MemoryStream memStream) {
 object sr;
 System.Runtime.Serialization.Formatters.Soap.SoapFormatter deserializer =
      new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
 memStream.Position=0;
 sr = deserializer.Deserialize(memStream);
 memStream.Close();
 return sr;
}
#endregion
  假如想對一個對象進行串行化處理,可以在它的前面添加[Serializable()]標(biāo)志,給類添加一個定制串行化屬性。在下面“Serialization”工程中的Schedule類中,我們會看到這一屬性。同時,我們還要考慮名字為[NonSerialized()]的字段屬性,它可以用于類中的所有字段,防止它被串行化,假如在類中有一個字段不需要或者我們不希望在正式產(chǎn)品中對某個字段進行串行化處理,這一點是非常有用的。只要簡單地在變量前添加NonSerialized()屬性即可,因為系統(tǒng)不會自動地對該變量進行串行化處理。

  需要記住的是,[Serializable()]屬性適用于整個類,因此假如希望整個類都支持串行化,我們必須添加屬性,而[NonSerialized()]屬性只適用于被標(biāo)志為[Serializable()]的類中的字段。使用[NonSerialized()]有時被稱作“有選擇性的串行化”。

  最后,需要記住的是,為了使用System.Runtime.Serialization.Formatters.Soap.SoapFormatter,我們必須添加System.Runtime.Serialization.Formatters.Soap.dll的引用。

  Figure 1.2 Schedule類


using System;

namespace FifteenSeconds {
///
/// 答應(yīng)我們提出一個計劃
///

[Serializable()]
public class Schedule {
PRotected System.DateTime start;
protected System.DateTime end;

//每次間隔增加的毫秒數(shù)
protected long interval;

public System.DateTime Start {get{return start;}set{start=value;}}
public System.DateTime End {get{return end;}set{end=value;}}
public long Interval {get{return interval;}set{interval=value;}}
public Schedule(System.DateTime Start, System.DateTime End, long Interval) {
start=Start;
end=End;
interval=Interval;
}
//返回下次運行的時間;假如計劃已經(jīng)結(jié)束,則返回結(jié)束時間
public System.DateTime NextRunTime {
get {
System.TimeSpan ts = new System.TimeSpan(end.Ticks-System.DateTime.Now.Ticks);
if(ts.Milliseconds>0) {
//運行時間還沒有結(jié)束
return System.DateTime.Now.AddMilliseconds(interval);
} else {
return end;
}
}
}
}


} 二進制和XML串行化的比較

  象上面表明的那樣,選擇XML或二進制串行化不取決于代碼的實現(xiàn)。二種方法實現(xiàn)起來都非常簡單。下面我們來考慮二種方法各自的優(yōu)點。

  二進制串行化的優(yōu)點

  1、無論是否是只讀屬性,所有成員都將被串行化。

  2、更高的性能。

  XML串行化的優(yōu)點

  1、對象共享和使用方面更大的靈活性(互操作性)。

  2、不嚴格的二進制依靠

  3、可讀性

  在研究Figure 1.1中的代碼后,我們會發(fā)現(xiàn),二進制和XML串行化僅僅依靠于對Formatter的選擇。我們還會發(fā)現(xiàn),串行化和反串行化之間的差別就在于是調(diào)用Serialize()還是Deserialize()。上面的代碼能夠原封不動地拷貝到我們的應(yīng)用程序中,它將成為我們大多數(shù)串行化需求的核心
基本串行化和定制串行化的比較

  .NET Framework提供了二種完成串行化的方式。需要記住的是,完成串行化的方式與串行化的格式是二個不同的概念,執(zhí)行串行化是指.NET Framework如何獲得我們對象、以及如何將它轉(zhuǎn)化為最后結(jié)果的實際方式,與格式(二進制還是XML格式無關(guān))。最簡單的方法是讓.NET Framework自動地對對象進行串行化操作,這種方式被稱作“基本串行化”?!盎敬谢敝灰髮ο髶碛蓄悓傩訹Serializable()]即可,.NET Framework將獲得我們的類,并將它轉(zhuǎn)換為給定的格式。在這種方法中,我們唯一能夠施加影響的是,使用[NonSerialized()]字段屬性使任何字段式不會被串行化,我們無法對類中的每個字段是如何被串行化的提供精確的控制。

  假如希望對串行化處理有更多的控制,就需要使用“定制串行化”。在這種方式中,我們能夠精確地指定哪個字段能夠被串行化,以及如何進行串行化。在樣例解決方案中,我們創(chuàng)建了一個名字為ScheduleCustom的類,正確地演示了“定制串行化”的用法。

  在使用“基本串行化”時,對象的版本是一個主要問題。要將Schedule對象串行化到磁盤上,然后改變該對象(例如,添加一個字段),在進行反串行化時就會出現(xiàn)問題,得到如下所示的錯誤信息:

“成員的數(shù)量發(fā)生錯誤,F(xiàn)ifteenSeconds.Schedule對象有4個成員,被反串行化的成員數(shù)量為3?!?br />
  假如碰上這一問題,就要考慮使用“定制串行化”了。由于能夠在串行化處理過程中精確地控制類中的所有成員,我們就能夠解決因版本而出現(xiàn)的問題。

  定制串行化

  我們需要作的第一件事就是明確地在類前面添加[Serializable()];第二,我們的類必須實現(xiàn)
System.Runtime.Serialization.ISerializable接口,因此,我們的類的定義應(yīng)當(dāng)如下所示:

[Serializable()]
public class ScheduleCustom : System.Runtime.Serialization.ISerializable {
 //在接口中,我們能夠發(fā)現(xiàn)下面的一個方法:
 void GetObjectData(SerializationInfo info, StreamingContext context);
 //為了使類能夠很好地支持這一接口,我們還必須實現(xiàn)下面的GetObjectData()方法:
 public void GetObjectData(SerializationInfo info,StreamingContext context) {
 //利用info對象添加需要進行串行化的字段
 info.AddValue("start", start);
 info.AddValue("end", end);
 info.AddValue("interval", interval);
}
  僅僅通過上面這個簡單的例子,我們也許還不能深刻地體會到使用“定制串行化”的強大功能。下面,我們將增加類的復(fù)雜程度,演示“定制串行化”帶給我們串行化需求的靈活性:

  假如我們要檢查串行化過程中開始時DateTime值的輸出,就會發(fā)現(xiàn)它使用了缺省的Framework DateTime格式:

  2002-08-19T14:09:13.3457440-07:00

  假如要與其他不使用.NET Framework的人合作,并國際化地發(fā)布應(yīng)用程序,用格林威治時間來表示
DateTime值是比較明智的。下面我們來修改GetObjectData()方法,將開始和結(jié)束時的值轉(zhuǎn)換為格林威治時間。


public void GetObjectData(SerializationInfo info,StreamingContext context) {
 //使用info對象添加需要串行化的字段
 //為了更好地與別人合作,我們將把時間轉(zhuǎn)換為格林威治時間
 info.AddValue("start", System.TimeZone.CurrentTimeZone.ToUniversalTime(start));
 info.AddValue("end", System.TimeZone.CurrentTimeZone.ToUniversalTime(end));
 info.AddValue("interval", interval);
 info.AddValue("timeformat", "utc");
}
  8/19/2002 9:09:13 PM

  現(xiàn)在,轉(zhuǎn)換時的起始時間將成為如下的格林威治時間形式:

  8/19/2002 9:09:13 PM

  注重,我添加了一個名字為“timeformat”的屬性,在以后判定在串行化處理中使用哪種時間格式時,這一字段非凡有用。

  也可以考慮用其他格式輸出日期??紤]System.Globalization.DateTimeFormatInfo能夠提供哪幾種格式,例如,將DateTime轉(zhuǎn)換為自Unix“誕生”(1979年1月1日)后的時間,這樣可以更好地與非微軟的平臺進行集成)。我們也可以在類中添加一個可選的屬性,判定在被串行化時DateTime使用的格式。

  定制反串行化

  假如希望使對象能夠以定制方式被反串行化,需要使用一個定制構(gòu)建器。該構(gòu)建器的定義如下所示:

public ScheduleCustom (SerializationInfo info,StreamingContext context) {}
  我們必須實現(xiàn)這一方法。在schedule類中,我們的實現(xiàn)將把UTC(世界協(xié)調(diào)時間)轉(zhuǎn)換為本機上的DateTime格式。

public ScheduleCustom (SerializationInfo info,StreamingContext context) {
 //我們將日期/時間轉(zhuǎn)換回本地時間
 this.start = info.GetDateTime("start").ToLocalTime();
 this.end = info.GetDateTime("end").ToLocalTime();
 this.interval = info.GetInt32("interval");
}
  象我們在前面的“定制串行化”過程中指出的那樣,添加的timeformat字段能夠用來指定如何將串行化的時間轉(zhuǎn)換為本地對象所必需的DateTime格式,但由于在本例中我們只進行了與UTC時間之間的轉(zhuǎn)換,因此是相當(dāng)簡單的。

  使用Web服務(wù)的串行化

  在學(xué)習(xí)新的技術(shù)時,最重要的是學(xué)習(xí)這種技術(shù)如何使用。在這一部份中,我們將創(chuàng)建一個有二個方法的Web服務(wù):第一個方法使Framework以二進制的形式返回我們定制串行化的schedule對象,第二個方法以XML的格式返回相同的對象。

  我們只要簡單地添加一個帶有指向上面的串行化工程引用的新C# Web服務(wù)工程即可,然后,我們再創(chuàng)建上面所述的二個方法:

FifteenSeconds.ScheduleCustom customSchedule =
new FifteenSeconds.ScheduleCustom(System.DateTime.Now, System.DateTime.Now.AddHours(5), 10000);

[WebMethod]
public byte[] Get_Binary_Schedule() {
 return FifteenSeconds.Serializer.Serialize( customSchedule,
 FifteenSeconds.Serializer.SerializationFormat.Binary).ToArray();
}
[WebMethod]
public string Get_XML_Schedule() {
 return FifteenSeconds.Serializer.ConvertStreamToString
 (FifteenSeconds.Serializer.Serialize( customSchedule,
 FifteenSeconds.Serializer.SerializationFormat.Xml));
}
  需要注重的是,二個方法都使用了FifteenSeconds.ScheduleCustom對象的同一個實例,在二進制形式中返回byte[]型數(shù)據(jù),在XML形式中返回string型數(shù)據(jù)。

  需要記住的是,F(xiàn)ramework將自動地串行化我們的對象,根據(jù)使用的方法返回適當(dāng)類型的數(shù)據(jù)。另外,我們還需要一些時間研究解決方案中的Serialization工程,在將這些對象串行化為一個文件時,其中有些方法可能會有用。

  結(jié)論

  這篇文章演示了在應(yīng)用程序中使用串行化是如何簡單。在需要將一個對象的實例轉(zhuǎn)換為能夠方便地傳輸或保存的格式時,串行化可能就是一種選擇。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 合阳县| 西城区| 芦山县| 肇庆市| 龙陵县| 台北市| 东平县| 饶河县| 吉木乃县| 大竹县| 临江市| 烟台市| 靖江市| 昌乐县| 曲阜市| 桐梓县| 德阳市| 永泰县| 临西县| 红原县| 翼城县| 息烽县| 嵊州市| 若尔盖县| 南投县| 霞浦县| 宣城市| 福泉市| 辽阳市| 安国市| 富平县| 东至县| 大埔区| 稻城县| 宁远县| 扶余县| 武鸣县| 木里| 房产| 武清区| 崇明县|