The PropertyBag Serializer

PocketSOAP includes a serializer that will work with the standard COM property bag serialization model. This is what VB uses when you set a VB class to be Persistable. This make it easy to serialize VB objects to/from SOAP, in many cases this can save you from having to write a custom serializer.

See the samples page, for the actual VB projects for the this code.

Sample

So, we'll take our trusty address/phone sample from earlier, and use the property bag serializer to go to/from SOAP.
<address>
	<number>100</number>
	<street>Spear Street</street>
	<city>San Francisco</city>
	<state>CA</state>
	<zip>94107</zip>
	<phone>
		<area>415</area>
		<exchange>343</exchange>
		<number>3000</number>
	</phone>
</address>
So, we have a simple telephone class with 3 data fields, set it to peristable, and write the persistance code to read/write the values to the property bag
telephone.cls
Option Explicit

Public area As String
Public exchange As String
Public number As String

Private Sub Class_ReadProperties(PropBag As PropertyBag)
    area = PropBag.ReadProperty("area")
    exchange = PropBag.ReadProperty("exchange")
    number = PropBag.ReadProperty("number")
End Sub

Private Sub Class_WriteProperties(PropBag As PropertyBag)
    PropBag.WriteProperty "area", area
    PropBag.WriteProperty "exchange", exchange
    PropBag.WriteProperty "number", number
End Sub
We do the same for address
address.cls
Option Explicit

Public number As String
Public street As String
Public city As String
Public state As String
Public zip As String

Public phone As telephone

Private Sub Class_Initialize()
    Set phone = New telephone
End Sub

Private Sub Class_ReadProperties(p As PropertyBag)
    number = p.ReadProperty("number")
    street = p.ReadProperty("street")
    city = p.ReadProperty("city")
    state = p.ReadProperty("state")
    zip = p.ReadProperty("zip")
    Set phone = p.ReadProperty("phone")
End Sub

Private Sub Class_WriteProperties(p As PropertyBag)
    p.WriteProperty "number", number
    p.WriteProperty "street", street
    p.WriteProperty "city", city
    p.WriteProperty "state", state
    p.WriteProperty "zip", zip
    p.WriteProperty "phone", phone
End Sub

Note that we don't have to do anything special for the nested phone object.

The default configuration for the serializer factory automatically maps the propertybag serializer to any object that can be serialized with it, so we don't need to do anything special for sending one of these.

Dim e As CoEnvelope
Set e = New CoEnvelope
e.SetMethod "setaddress", "http://soap.address.org/"
e.Parameters.Create "address", GetAddress
MsgBox e.Serialize

Private Function GetAddress() As address
    Dim a As address
    Set a = New address
    a.Number = "100"
    a.street = "Spear Street"
    a.city = "San Francisco"
    a.state = "CA"
    a.zip = "94105"
    a.phone.area = "415"
    a.phone.exchange = "343"
    a.phone.Number = "3000"
    Set GetAddress = a
End Function
As the address and phone objects are persistable pocketSOAP will automatically serialize them with the property bag serializer, generating this SOAP message
<S:Envelope
	S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
	xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'
	xmlns:E='http://schemas.xmlsoap.org/soap/encoding/'
	xmlns:a='http://soap.address.org/'
	xmlns:b='http://www.w3.org/2001/XMLSchema-instance'
	xmlns:c='http://www.w3.org/2001/XMLSchema'>
<S:Body>
 <a:setaddress>
  <address href='#a'/>
 </a:setaddress>
<phone E:root='0' id='b'>
 <area b:type='c:string'>415</area>
 <exchange b:type='c:string'>343</exchange>
 <number b:type='c:string'>3000</number>
</phone>
<address E:root='0' id='a'>
 <number b:type='c:string'>100</number>
 <street b:type='c:string'>Spear Street</street>
 <city b:type='c:string'>San Francisco</city>
 <state b:type='c:string'>CA</state>
 <zip b:type='c:string'>94105</zip>
 <phone href='#b'/>
</address>
</S:Body></S:Envelope>

De-serializing one is only slightly more complicated, we just need to register a propertybag deserializer to handle the particular types. In this particular case, there is no xsi:type, so we also register element -> type mappings as well.

Dim e As CoEnvelope
Set e = New CoEnvelope
Dim sf As ISerializerFactoryConfig
Set sf = e.SerializerFactory
sf.ElementMapping "phone", "", "phone", "http://apache.org/"
sf.ElementMapping "address", "", "address", "http://apache.org/"
sf.Deserializer "phone", "http://apache.org/", False, "ps.telephone", "pocketSOAP.SerializerPB.1"
sf.Deserializer "address", "http://apache.org/", False, "ps.address", "pocketSOAP.SerializerPB.1"
    
e.SetMethod "setaddress", "http://soap.address.org/"
e.Parameters.Create "address", GetAddress
Dim s As String
s = e.Serialize
 
' parse the soap message we just generated   
e.Parse s
Dim a As address
Set a = e.Parameters.Item(0).Value
    
res.Text = a.Number & " " & a.street & "," & vbCrLf
res.Text = res.Text + a.city & "," & vbCrLf & a.state & " " & a.zip & vbCrLf
res.Text = res.Text + a.phone.area & " " & a.phone.exchange & " " & a.phone.Number



Copyright

Copyright © Simon Fell, 2000-2004. All rights reserved.