天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

WCF分布式開發(fā)步步為贏(7):WCF數(shù)據(jù)契約與序列化

  本節(jié)繼續(xù)學(xué)習(xí)WCF分布式開發(fā)步步為贏(7):WCF數(shù)據(jù)契約與序列化.數(shù)據(jù)契約是WCF應(yīng)用程序開發(fā)中一個(gè)重要的概念,毫無疑問實(shí)現(xiàn)客戶端與服務(wù)端數(shù)據(jù)契約的傳遞中序列化是非常重要的步驟。那么序列化是什么?為什么會(huì)有序列化機(jī)制?或者說它是為了解決什么問題?作用是什么?現(xiàn)有的.NET 序列化機(jī)制和WCF序列化機(jī)制有什么不同?我們在本節(jié)文章里都會(huì)詳細(xì)介紹。

  下面我們正式進(jìn)入今天的學(xué)習(xí)階段,首先來介紹一下數(shù)據(jù)契約的概念:

  【0】數(shù)據(jù)契約(DataContract):

   在WCF服務(wù)編程中我們知道,服務(wù)契約定義了遠(yuǎn)程訪問對象和可供調(diào)用的服務(wù)操作方法,數(shù)據(jù)契約則是定義服務(wù)端和客戶端之間要傳送的自定義數(shù)據(jù)類型。在WCF項(xiàng)目中,聲明一個(gè)類型為DataContract,那么該類型就可以被序列化在服務(wù)端和客戶端之間傳送。類只有聲明為DataContract,該類型的對象才可以被傳送,且只有類的屬性會(huì)被傳送,需要在屬性生命前加DataMember聲明,這樣該屬性就可以被序列化傳送。默認(rèn)情況屬性是不可傳遞的。類的方法不會(huì)被傳送。WCF對定義的數(shù)據(jù)契約的類型可以進(jìn)行更加細(xì)節(jié)的控制,可以把一個(gè)成員屬性排除在序列化范圍以外,客戶端程序不會(huì)獲得被排除在外的成員屬性的任何信息,包括定義和數(shù)據(jù)。  代碼如下:

 [DataContract]//數(shù)據(jù)契約屬性聲明
    class MyDataContract
    {
        [DataMember(Name 
= "MyName")]//數(shù)據(jù)成員標(biāo)記,支持別名定義
        public string Name
        {
            
get;
            
set;
        }
        [DataMember(Name 
= "MyEmail")]//數(shù)據(jù)成員標(biāo)記,支持別名定義
        public string Email
        {
            
get;
            
set;
        }
        [DataMember]
//數(shù)據(jù)成員標(biāo)記
        public string Mobile
        {
            
get;
            
set;
        }
        
//沒有[DataMember]聲明,不會(huì)被序列化
        public string Address
        {
            
get;
            
set;
        }
    }
}

  【1】序列化基本概念:

  知道數(shù)據(jù)契約的一些概念和特性之后,下面來介紹一下序列化的概念。

  【1.1】為什么序列化:我們這里先來介紹一下為什么需要序列化。當(dāng)然這個(gè)不是必須的。只是針對特定的開發(fā)平臺的數(shù)據(jù)或者信息類型而言,當(dāng)一個(gè)系統(tǒng)或者說平臺需要和別的異構(gòu)的系統(tǒng)或者平臺交互的時(shí)候,兩個(gè)系統(tǒng)需要一個(gè)特定的公開的可以公用的行業(yè)標(biāo)準(zhǔn)來支持這個(gè)數(shù)據(jù)信息的交互。這里目前來說支持這個(gè)數(shù)據(jù)交互傳遞的語言載體就是XML.

  同樣WCF作為面向服務(wù)的編程框架,它的目標(biāo)或者特性之一就是實(shí)現(xiàn)服務(wù)的跨語言、平臺,與不同的服務(wù)進(jìn)行信息數(shù)據(jù)的交互,而不限制客戶端的系統(tǒng)或者開發(fā)語言。要實(shí)現(xiàn)這個(gè)目標(biāo),WCF服務(wù)首先就是要面對信息的傳遞與共享問題。我們知道WCF服務(wù)和客戶端可以傳遞如Int、String等.NET數(shù)據(jù)類型。但是如何實(shí)現(xiàn)用戶自定義復(fù)雜類型的跨服務(wù)邊界的傳遞,這是一個(gè)關(guān)鍵問題。數(shù)據(jù)契約可以發(fā)布為服務(wù)的元數(shù)據(jù),允許客戶端轉(zhuǎn)化為本地語言表示。解決的辦法就是封送(Marshaling),將對象封送到其它平臺。基于WCF的客戶端和服務(wù)端參數(shù)傳遞的過程如下圖:

  主要步驟:客戶端序列化參數(shù)為XML信息集--傳遞->服務(wù)端反序列化為本地類型--執(zhí)行結(jié)果->序列化結(jié)果為XML信息集--傳遞->客戶端序反序列化返回信息為本地類型。

  在WCF分布式開發(fā)必備知識(2):.NET Remoting一節(jié)中也介紹了.NET Remoting的通信過程 ,兩者也有流程也有部分相似之處。對象封送的概念其實(shí).NET Remoting早有涉及,遠(yuǎn)程對象(RemoteOject),也就是我們遠(yuǎn)程要訪問的對象.首先定義一個(gè)Class,繼承MarshalByRefObject,可以使用在remoting應(yīng)用中,支持對象的跨域邊界訪問。看過.NET Remoting這節(jié)文章應(yīng)該還有點(diǎn)印象,不同之處是WCF的對象封送是為跨越服務(wù)邊界,.NET Remoting的封送是為了跨越跨域邊界。相關(guān)的概念請查閱WCF分布式開發(fā)必備知識(2):.NET Remoting或者M(jìn)SDN,都能找到詳細(xì)的介紹,這里不在詳述。

  【1.2】什么是序列化:

  序列化是指將對象實(shí)例的狀態(tài)存儲存儲媒體的過程。在此過程中,先將對象的公共字段和私有字段以及類的名稱(包括類所在的程序集)轉(zhuǎn)換為字節(jié)流,然后再把字節(jié)流寫入數(shù)據(jù)流。在隨后對對象進(jìn)行反序列化時(shí),將創(chuàng)建出與原對象完全相同的副本。

  用戶自定義類型要想在WCF服務(wù)端和客戶端傳遞就必須聲明為DataContract。這樣就能實(shí)現(xiàn)用戶自定義類型的序列化。序列化的目的就是把一種私有的或者某種平臺下使用的數(shù)據(jù)類型轉(zhuǎn)化為標(biāo)準(zhǔn)的可以公開交互的數(shù)據(jù)信息樣式。這個(gè)過程就叫序列化。這個(gè)也是序列化的作用或者目的之所在。序列化是將對象狀態(tài)轉(zhuǎn)換為可保持或傳輸?shù)母袷降倪^程。與序列化相對的是反序列化,它將流轉(zhuǎn)換為對象。這兩個(gè)過程結(jié)合起來,可以輕松地存儲和傳輸數(shù)據(jù)。序列化的目的:

  1、以某種存儲形式使自定義對象持久化;

  2、將對象從一個(gè)地方傳遞到另一個(gè)地方。 序列化就是把本地消息或者數(shù)據(jù)的類型進(jìn)行封送,轉(zhuǎn)換為標(biāo)準(zhǔn)的可以跨平臺、語言的信息集,為別的系統(tǒng)或者服務(wù)所用。

  【2】.NET 序列化機(jī)制:

  .NET的序列化。.NET是通過反射機(jī)制自動(dòng)實(shí)現(xiàn)對象的序列化與反序列化。首先.NET能夠捕獲對象每個(gè)字段的值,然后進(jìn)行序列化,反序列化時(shí),.NET創(chuàng)建一個(gè)對應(yīng)類型的新的對象,讀取持久化的值,然后設(shè)置字段的值。.NET對象狀態(tài)的序列化到Stream中。.NET Framework 提供三種序列化技術(shù):

  1.BinaryFormatter二進(jìn)制序列化保持類型保真度,這對于在應(yīng)用程序的不同調(diào)用之間保留對象的狀態(tài)很有用。例如,通過將對象序列化到剪貼板,可在不同的應(yīng)用程序之間共享對象。您可以將對象序列化到流、磁盤、內(nèi)存和網(wǎng)絡(luò)等等。遠(yuǎn)程處理使用序列化“通過值”在計(jì)算機(jī)或應(yīng)用程序域之間傳遞對象。

     2.調(diào)用System.Runtime.Serialization.Formatters.Soap空間下的SoapFormatter類進(jìn)行序列化和反序列化,序列化之后的文件是Soap格式的文件(簡單對象訪問協(xié)議(Simple Object Access Protocol,SOAP),WCF分布式開發(fā)必備知識(4):Web Service也進(jìn)行了介紹,SOAP是一種輕量的、簡單的、基于XML的協(xié)議,它被設(shè)計(jì)成在WEB上交換結(jié)構(gòu)化的和固化的信息。 SOAP 可以和現(xiàn)存的許多因特網(wǎng)協(xié)議和格式結(jié)合使用,包括超文本傳輸協(xié)議(HTTP),簡單郵件傳輸協(xié)議(SMTP),多用途網(wǎng)際郵件擴(kuò)充協(xié)議(MIME)。它還支持從消息系統(tǒng)到遠(yuǎn)程過程調(diào)用(RPC)等大量的應(yīng)用程序。 SOAP使用基于XML的數(shù)據(jù)結(jié)構(gòu)和超文本傳輸協(xié)議(HTTP)的組合定義了一個(gè)標(biāo)準(zhǔn)的方法來使用InterNET上各種不同操作環(huán)境中的分布式對象。可以實(shí)現(xiàn)跨平臺數(shù)據(jù)的交互。

  3.XML 序列化需要引用System.Xml.Serialization,使用XmlSerialize類進(jìn)行序列化和反序列化操作。它僅序列化公共屬性和字段,且不保持類型保真度。基于XML 標(biāo)準(zhǔn),支持跨平臺數(shù)據(jù)交互。

    BinaryFormatter二進(jìn)制序列化的優(yōu)點(diǎn):1. 所有的類成員(包括只讀的)都可以被序列化;2. 性能高。

    SoapFormatter、XmlSerialize的優(yōu)點(diǎn):1. 跨平臺,互操作性好;2. 不依賴二進(jìn)制;3. 可讀性強(qiáng)。

    當(dāng)然.NET原有的序列化器也有自己的局限性,因?yàn)樗麄兂艘蛄谢瘜ο蟮臓顟B(tài)信息外,還要將程序集的信息和版本信息持久化到流中,這樣才能保證對象被反序列化為正確的對象類型副本。這要求客戶端必須擁有使用.NET程序集。不能滿足跨平臺的WCF數(shù)據(jù)交互的需求。

  【3】WCF序列化機(jī)制:

  由于.NET格式化器固有的缺陷,WCF不得不提供自己的格式化,以滿足其面向服務(wù)的需求。在WCF程序集里,提供了專門用戶序列化和反序列化操作的類:DataContractSerializer,在System.Runtime.Serialization命名空間里。使用Reflector查看其定義信息如下:

public abstract class XmlObjectSerializer
{
    
// Methods
    protected XmlObjectSerializer()
    {
    }
    
internal static void CheckNull(object obj, string name)
    {
        
if (obj == null)
        {
            
throw new ArgumentNullException(name);
        }
    }
    
internal virtual Type GetSerializeType(object graph)
    {
        
if (graph != null)
        {
            
return graph.GetType();
        }
        
return null;
    }
    
private static string GetTypeInfoError(int errorMessage, Type type, Exception
innerException)
    {
        
string str = (type == null? string.Empty : SR.GetString(1new object[]
{ DataContract.GetClrTypeFullName(type) });
        
string str2 = (innerException == null? string.Empty : innerException.Message;
        
return SR.GetString(errorMessage, new object[] { str, str2 });
    }

    
public abstract bool IsStartObject(XmlDictionaryReader reader);
    
public virtual bool IsStartObject(XmlReader reader)
    {
        CheckNull(reader, 
"reader");
        
return this.IsStartObject(XmlDictionaryReader.CreateDictionaryReader(reader));
    }

    
public virtual object ReadObject(XmlDictionaryReader reader)
    {
        
return this.ReadObject(reader, true);
    }
    
public virtual object ReadObject(XmlReader reader)
    {
        CheckNull(reader, 
"reader");
        
return this.ReadObject(XmlDictionaryReader.CreateDictionaryReader(reader));
    }
    
public abstract object ReadObject(XmlDictionaryReader reader, bool
verifyObjectName);
    
public virtual object ReadObject(XmlReader reader, bool verifyObjectName)
    {
        CheckNull(reader, 
"reader");
        
return this.ReadObject(XmlDictionaryReader.CreateDictionaryReader(reader),
verifyObjectName);
    }

    
public abstract void WriteEndObject(XmlDictionaryWriter writer);
    
public virtual void WriteEndObject(XmlWriter writer)
    {
        CheckNull(writer, 
"writer");
        
this.WriteEndObject(XmlDictionaryWriter.CreateDictionaryWriter(writer));
    }
    
public virtual void WriteObject(XmlDictionaryWriter writer, object graph)
    {
        CheckNull(writer, 
"writer");
        
try
        {
            
this.WriteStartObject(writer, graph);
            
this.WriteObjectContent(writer, graph);
            
this.WriteEndObject(writer);
        }
        
catch (XmlException exception)
        {
            
throw new SerializationException(GetTypeInfoError(0this.GetSerializeTy
pe(graph), exception), exception);
        }
        
catch (FormatException exception2)
        {
            
throw new SerializationException(GetTypeInfoError(0this.GetSerializeTy
pe(graph), exception2), exception2);
        }
    }
    
public virtual void WriteObject(XmlWriter writer, object graph)
    {
        CheckNull(writer, 
"writer");
        
this.WriteObject(XmlDictionaryWriter.CreateDictionaryWriter(writer), graph);
    }
    
public abstract void WriteObjectContent(XmlDictionaryWriter writer, object
graph);
    
public virtual void WriteObjectContent(XmlWriter writer, object graph)
    {
        CheckNull(writer, 
"writer");
        
this.WriteObjectContent(XmlDictionaryWriter.CreateDictionaryWriter(writer),
graph);
    }
    
public abstract void WriteStartObject(XmlDictionaryWriter writer, object graph);
    
public virtual void WriteStartObject(XmlWriter writer, object graph)
    {
        CheckNull(writer, 
"writer");
        
this.WriteStartObject(XmlDictionaryWriter.CreateDictionaryWriter(writer),
 graph);
    }
}

  【4】代碼實(shí)現(xiàn)與分析:

  下面是示例代碼的具體實(shí)現(xiàn)過程,這里做簡要的講解.

  【4.1】數(shù)據(jù)契約:

  我們定義了一個(gè)數(shù)據(jù)契約類UserDataContract,包含簡單的幾個(gè)屬性Name、Email、Mobile,分別用來存儲用戶名、電子郵件、手機(jī)信息,代碼如下:

  [DataContract]//數(shù)據(jù)契約屬性聲明
    class UserDataContract
    {
        [DataMember(Name 
= "UserName")]//數(shù)據(jù)成員標(biāo)記,支持別名定義
        public string Name
        {
            
get;set;
        }
        [DataMember(Name 
= "UserEmail")]//數(shù)據(jù)成員標(biāo)記,支持別名定義
        public string Email
        {
            
get;set;
        }
        [DataMember]
//數(shù)據(jù)成員標(biāo)記
        public string Mobile
        {
            
get;set;
        }
        
//沒有[DataMember]聲明,不會(huì)被序列化
        public string Address
        {
            
getset;
        }
    }

NET技術(shù)WCF分布式開發(fā)步步為贏(7):WCF數(shù)據(jù)契約與序列化,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 亚洲无遮挡无码A片在线 | 欧美日韩亚洲第一区在线 | 一区二区三区四区国产 | 美女的避毛| 日日摸天天添天天添无码蜜臀 | 国产午夜亚洲精品区 | 亚洲中文字幕无码一去台湾 | 最近的2019中文字幕HD | 制服的微热| 粉色视频午夜网站入口 | 一本色道久久综合亚洲精品蜜桃冫 | 久久99re6热在线播放 | 翘臀少妇被扒开屁股日出水爆乳 | 久久亚洲AV无码精品午色夜麻豆 | 99久久国产视频 | 日本人bbwbbwbbwbbw | 精品午夜国产福利观看 | 扒开屁股眼往里面夹东西 | 国产福利视频第一导航 | 国产精品久久vr专区 | 樱花草动漫www | 欧美日韩一二区旡码高清在线 | 97精品视频在线观看 | 24小时日本在线电影 | 午夜dj免费中文字幕 | 2021久久99国产熟女人妻 | 欧美含羞草免费观看全部完 | 邪恶肉肉全彩色无遮琉璃神社 | 墨西哥美女主播 | 古代荡女丫鬟高H辣文纯肉 姑娘视频日本在线播放 | 夜色私人影院永久入口 | 国产色偷偷男人的天堂 | 叔叔 电影完整版免费观看韩国 | 啦啦啦 中国 日本 高清 在线 | 乱码中字在线观看一二区 | 美美哒高清在线播放8 | 青春草久久 | 色欲AV亚洲午夜精品无码 | av无码在线日本天堂 | 91偷偷久久做嫩草电影院 | 亚洲第一综合天堂另类专 |