(7)序列化與壓縮

來源:互聯網
上載者:User

因為ServiceObject的函數簽名格式是統一的,可以傳遞的參數只有一個AParams:OLEVariant,用戶端的多個參數需要使用數組傳遞。如:

var<br /> vParams:OLEVariant;<br /> vResult:integer;<br />begin<br /> ...<br /> vParams:=VarArrayCreate([0,1],varVariant);<br /> vParams[0]:=3;<br /> vParams[1]:=2;<br /> ...<br /> vResult:=BizService.Call('system.Test','Sum',vParams);

但是這種方式不太直觀,AParams內部的元素嚴重依賴順序,一旦寫好,很難改變。另一種方式是使用序列化的Object,如:

TMarshalSumParams=class<br />published<br /> A:integer;<br /> B:integer<br />end;

使用某種編碼方式,把這個元件序列化成一個stream,這樣就很容易傳遞到伺服器,伺服器的ServiceObject再把stream還原序列化TMarshalSumParams。

序列化在delphi中,有兩種方式可以利用:

1、使用TWriter和TReader。這兩個元件,是delphi用來讀寫其dfm檔案的,你在剪下/黏貼元件時,也是它們在工作。但是兩個元件唯寫元件published屬性,也沒有專門考慮來做用戶端伺服器的序列化,所以任何published不支援的資料類型,它都不處理,如動態數組,Variant也只支援byte數組。這裡需要修改。TWriter寫出的是二進位流,效率比文本高。

procedure TVariantWriter.WriteArray(const Value: Variant);<br />var<br /> i:integer;<br /> Lo,Hi:integer;<br />begin<br /> WriteValue(vaArray);<br /> Lo:=VarArrayLowBound(Value,1);<br /> Hi:=VarArrayHighBound(Value,1);<br /> Write(Lo,SizeOf(integer));<br /> Write(Hi,SizeOf(integer));<br /> for i:=Lo to Hi do WriteVariant(Value[i]);<br />end;</p><p>procedure TVariantWriter.WriteVariant(const Value: Variant);<br />var<br /> CustomType: TCustomVariantType;<br /> OuterStream, InnerStream: TMemoryStream;<br /> OuterWriter: TWriter;<br /> StreamSize: Integer;<br /> VarStreamer: IVarStreamable;<br /> LInt64: Int64;<br />begin<br /> if VarIsArray(Value) then<br /> begin<br /> if (VarType(Value) and varByte)=varByte then<br /> WriteByteArray(Value)<br /> else<br /> WriteArray(Value);<br /> end<br /> else<br /> case VarType(Value) and varTypeMask of<br /> varEmpty:<br /> WriteValue(vaNil);<br /> varNull:<br /> WriteValue(vaNull);<br /> varOleStr:<br /> WriteWideString(Value);<br /> varString:<br /> WriteString(Value);<br /> varByte, varShortInt, varWord, varSmallInt, varInteger:<br /> WriteInteger(Value);<br /> varSingle:<br /> WriteSingle(Value);<br /> varDouble:<br /> WriteFloat(Value);<br /> varCurrency:<br /> WriteCurrency(Value);<br /> varDate:<br /> WriteDate(Value);<br /> varBoolean:<br /> if Value then<br /> WriteValue(vaTrue)<br /> else<br /> WriteValue(vaFalse);<br /> varLongWord, varInt64:<br /> begin<br /> LInt64 := Value;<br /> WriteInteger(LInt64);<br /> end;<br /> else<br /> try<br /> if not FindCustomVariantType(TVarData(Value).VType, CustomType) or<br /> not Supports(Value, IVarStreamable, VarStreamer) then<br /> WriteString(Value)<br /> else<br /> begin<br /> InnerStream := nil;<br /> OuterStream := TMemoryStream.Create;<br /> try<br /> InnerStream := TMemoryStream.Create;<br /> OuterWriter := TWriter.Create(OuterStream, 1024);<br /> try<br /> VarStreamer.StreamOut(TVarData(Value), InnerStream);<br /> StreamSize := InnerStream.Size;</p><p> OuterWriter.WriteString(CustomType.ClassName);<br /> OuterWriter.Write(StreamSize, SizeOf(StreamSize));<br /> OuterWriter.Write(InnerStream.Memory^, StreamSize);<br /> finally<br /> OuterWriter.Free;<br /> end;<br /> StreamSize := OuterStream.Size;<br /> WriteValue(vaBinary);<br /> Write(StreamSize, SizeOf(StreamSize));<br /> Write(OuterStream.Memory^, StreamSize);<br /> finally<br /> InnerStream.Free;<br /> OuterStream.Free;<br /> end;<br /> end;<br /> except<br /> raise EWriteError.CreateRes(@SWriteError);<br /> end;<br /> end;<br />end;

2、使用SOAP對TRemotable元件的編碼方式,編碼成XML格式。同樣它對Variant只支援byte數組,如果你要支援別的variant類型,需要自己改造。需要說明的是,XML編碼效率比較低,資料量越大越明顯。

function TMarshalComponent._MarshalToXMLStream(<br /> AStream: TStream): WideString;<br />const<br /> Signature:WideChar=#$FEFF;<br />var<br /> vDoc:IXMLDocument;<br /> vConverter:IObjConverter;<br /> {$IFDEF Ver150}<br /> RefID:WideString;<br /> {$ELSE}<br /> RefID:InvString;<br /> {$ENDIF}<br />begin<br />//為何輸出的XML檔案沒有encoding?<br /> ActiveX.CoInitialize(nil);<br /> vDoc:=TXMLDocument.Create(nil);<br /> try<br /> (vDoc as IXMLDocumentAccess).DocumentObject.DOMVendor:=GetDOMVendor(sMSXML);<br /> vDoc.Active:=true;</p><p> vDoc.Version:='1.0';<br /> vDoc.StandAlone:='yes';<br /> vDoc.Encoding:='utf-8';</p><p> vDoc.DocumentElement:=vDoc.CreateNode(Self.ClassName);<br /> vConverter:=OPToSOAPDomConv.TOPToSoapDomConvert.Create(nil);<br /> try<br /> vConverter.ObjInstanceToSOAP(Self,vDoc.DocumentElement,vDoc.DocumentElement,<br /> Self.ClassName,'',[],RefID);<br />//用SaveToStream編碼有問題<br /> vDoc.SaveToXML(Result);<br />//需要增加簽名,否則IE打不開<br /> Result:=Signature+Result;<br /> if AStream<>nil then<br /> begin<br /> AStream.Size:=0;<br /> AStream.Write(Result[1],Length(Result)*2);<br /> end;<br /> vDoc.Active:=false;<br /> finally<br /> vConverter:=nil;<br /> end;<br /> finally<br /> vDoc:=nil;<br /> ActiveX.CoUninitialize;<br /> end;<br />end;

 

在Delphi2010的時候,支援了Json格式的序列化,它應該是比XML更高效的一種方式。

一旦序列化成stream,我們就可以使用任何壓縮方式在傳遞前壓縮,如zlib,leo,等。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.