<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>
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 phone.cls Option Explicit Public area As String Public exchange As String Public number As StringNow, lets write some code that create's one of these and sets up the values, and then passes it to pocketSOAP
dim adr set adr = CreateObject("samples.address") adr.number = "100" adr.street = "Spear Street" adr.city = "San Francisco" adr.state = "CA" adr.zip = "94107" adr.phone.area = "415" adr.phone.exchange = "343" adr.phone.number = "3000" dim env set env = CreateObject("pocketSOAP.Envelope.2") env.SetMethod "addAddress", "http://address.example.org/" env.Parameters.Create "address", adr
addrserializer.cls Option Explicit Implements ISoapSerializer Private Sub ISoapSerializer_Serialize(V As Variant, _ ByVal ctx As PocketSOAP.ISerializerContext, _ ByVal dest As PocketSOAP.ISerializerOutput) ' pocketSOAP will call us at the point it wants the address object serializing out, ' V will contain the address object instance to serialize ' in turn, all we do is ask it to serialize the child items for us dest.SerializeValue V.number, "number", "" dest.SerializeValue V.street, "street", "" dest.SerializeValue V.city, "city", "" dest.SerializeValue V.state, "state", "" dest.SerializeValue V.zip, "zip", "" dest.SerializeValue V.phone, "phone", "" End SubNow that last line ask pocketSOAP to serialize a phone object, so we'll need to write a serializer for that as well
phoneserializer.cls Option Explicit Implements ISoapSerializer Private Sub ISoapSerializer_Serialize(V As Variant, _ ByVal ctx As PocketSOAP.ISerializerContext, _ ByVal dest As PocketSOAP.ISerializerOutput) ' pocketSOAP will call us at the point it wants the phone object serializing out, ' V will contain the phone object instance to serialize ' in turn, all we do is ask it to serialize the child items for us dest.SerializeValue V.area, "area", "" dest.SerializeValue V.exchange, "exchange", "" dest.SerializeValue V.number, "number", "" End SubFinally, we need to tell pocketSOAP that it can use these serializers to serializer instances of the address & phone objects.
.... dim env set env = CreateObject("pocketSOAP.Envelope.2") env.SerializerFactory.Serializer "{AC02D0F2-A2A1-4cba-8589-5E4CC2250D81}", "address", "http://address.example/org", "samples.addrserializer" env.SerializerFactory.Serializer "{870C6692-F3C1-4684-B1AE-47B6ED81604C}", "phone", "http://address.example/org", "samples.phoneserializer" env.SetMethod "addAddress", "http://address.example.org/" env.Parameters.Create "address", adrNow, pocketSOAP uses Interface ID's to regognise particular objects, if you're not a COM programmer, then that might not make any sense, Once you build the project with the address & phone objects in, you'll be able to find the Interface ID's from the resulting DLL. Run oleview select file->view typelib and open the DLL you've just built. Looking at the library file, you'll see a list of all the properies on the object, something like
[ odl, uuid(0B451395-7AFF-44E8-BF88-CF35FB1A34D6), version(1.0), hidden, dual, nonextensible, oleautomation, custom(50867B00-BB69-11D0-A8FF-00A0C9110059, 4) ] interface _address : IDispatch { [id(0x40030000), propget] HRESULT number([out, retval] BSTR* number); [id(0x40030000), propput] HRESULT number([in] BSTR number); [id(0x40030001), propget] HRESULT street([out, retval] BSTR* street); [id(0x40030001), propput] HRESULT street([in] BSTR street); [id(0x40030002), propget] HRESULT city([out, retval] BSTR* city); [id(0x40030002), propput] HRESULT city([in] BSTR city); [id(0x40030003), propget] HRESULT state([out, retval] BSTR* state); [id(0x40030003), propput] HRESULT state([in] BSTR state); [id(0x40030004), propget] HRESULT zip([out, retval] BSTR* zip); [id(0x40030004), propput] HRESULT zip([in] BSTR zip); [id(0x40030005), propget] HRESULT phone([out, retval] _phone** phone); [restricted] void Missing18(); [id(0x40030005), propputref] HRESULT phone([in] _phone* phone); };The long number in the uuid section is the Interface ID, copy this into your call to Serializer, and repeat for the phone object.
In many cases, VB uses may prefer to use the propertybag serializer, which doesn't need specific interface ID's to use.
As of pocketSOAP 1.2, the serializerFactory maintains a pool of created serializers, that can be re-used during the [de]serialization process. In this case the serializerFactory will create a single instance of the serializer and make multiple calls to the Serialize function. In the case of the de-serialization process, the deserializer should release all its resources when End is called, once End has been called, the de-serializer is returned to the pool, and it may be asked to de-serialize further items, by start getting called again.
Its highly recommended that if you're going to use either a custom serializer or the propertybag serializer, that you define interfaces to your objects in IDL, and compile them to a typelibrary, and have your VB objects implement the particular interfaces. This gives you much more control over interface versioning, whereas if you leave it to VB, it can and will change the interface ID's on you, breaking the code that maps in your serializers. The full scope on COM for VB programs is way out of scope for pocketSOAP, i'd highly recommend you look at a good COM/VB book such as Ted Patison's excellent Programming Distributed Applications with COM+ and Microsoft Visual Basic 6.0
Copyright © Simon Fell, 2000-2004. All rights reserved.