WSDAPI 101 Part 3: Generated code and what it does for you
This is the third article in the WSDAPI 101 series. You'll learn the most by starting at the beginning, although it's not required to understand the content in this article.
Now that we understand the layering presented in WSDAPI 101: Part 2, we can dig into the magical goodness that is generated code--if Web Services had a caramel-filled center, this would be it. It's also the middle layer in the diagram at right.
The most important characteristic of generated code is that it works like an adapter between the generic WS stack and the application-layer interface, defined by the wire contract. It's OK if you don't understand everything in that last sentence--just remember that generated code is specific to the WS stack, and it's also specific to your application.
Because it's specific to the WS stack, the generated layer for WSDAPI looks remarkably different from the generated layer for Windows Communication Foundation (WCF) or any other stack. The concepts I describe in this article apply across the board, but are told from the WSDAPI perspective.
Let's take a look inside
OK, time to dive into the code. WSDAPI's generated layer can be organized into five different components:
- Types, which define the C++ representation of the XML types in your message. You'll use these types directly in your application layer. In the webcam example, you may have a WEBCAM_RESOLUTION_TYPE, which is a structure with two integers inside.
- Interfaces, which define a service's porttypes and operations as C++ classes and methods. If you're building a client, you'll call into these methods. If you're building a service, you'll expose these methods. IWebcam is that interface, and it'll have methods like GetWebcamImage(image*) and SetWebcamResolution(WEBCAM_RESOLUTION_TYPE)
- Proxy classes, client-side objects which wrap WSDAPI to look like the services you're connecting to. Proxy classes are probably the first things that come to mind when you think of "generated code." In this case, think CWebcamProxy, which implements IWebcam.
- Stub functions, service-side objects which accept incoming generic calls from WSDAPI and translate them to contract-specific calls to your service object. These are similar to proxies, but work the other direction. I'll skip these for now; you'll see why later.
- Everything else. WSDAPI gives you a lot of other stuff to play with inside generated code. Some of it is to make it easier to deal with constructs in the world of Devices Profile for Web Services (e.g., static metadata structures) and others are provided merely as a convenience (e.g., proxy builder functions). These things are helpful, but aren't core to the WS experience.
With the exception of the "everything else" category, the items above are listed in order of decreasing importance. As a client or service developer, you'll probably have to know a lot about your types and interfaces, but very little about your proxy classes and typically nothing about stub functions. This is why I omit stub functions above: in WSDAPI-land, you shouldn't ever have to deal directly with a stub function.
I've added two diagrams at right: the first shows how these generated items are organized if you're building a client application; the second shows the same for a service application. In both cases, all of the generated content (red boxes) are contained in a handful of files, but they end up getting pulled into different layers in your application stack, so that's why they appear all over the place.
How these five items are arranged in files
So first, let's talk about how you generate this code. Generated code for WSDAPI-based applications comes from the WsdCodeGen tool the WSDAPI team publishes. The following is a slight oversimplification, but you can run the WsdCodeGen tool on a set of WSDLs, and it will produce a bunch of C++ and IDL files. And for those of you who don't already know, WsdCodeGen is available in the various iterations of the Windows SDK (Vista SDK, Server 2008 SDK, etc.).
So let's say you've got your Webcam WSDL and you've run it through WsdCodeGen. You'll end up with six core files:
- Webcam.idl: This IDL contains the interfaces described above. You can use the MIDL tool to compile this into C++ files (Visual Studio knows how this needs to happen). You can learn all about IWebcam by looking in this file.
- WebcamTypes.h: This header contains the type definitions. You can learn all about things like WEBCAM_RESOLUTION_TYPE inside this file.
- WebcamTypes.cpp: This source file contains lots of other stuff. Don't poke around in here unless you're really curious (or are looking for a way to deal with insomnia).
- WebcamProxy.h: This defines a proxy class that typically extends the interface described in Webcam.idl. It's not a bad idea to check this out.
- WebcamProxy.cpp: Another source file with "other stuff." Again, boring.
- WebcamStub.cpp: This source file defines stub functions. Don't bother unless you're bored.
Of course, WsdCodeGen automatically chooses these filenames so they're somewhat appropriate for your application, so if you're building a network-attached blender, then it's unlikely you'll end up with files starting with "Webcam."
Can I look inside the generated code?
Absolutely. In fact, I was originally going to post the contents of the proxy code for one of our sample applications, but this post has since grown to be way longer than I originally expected, so I won't bloat it even more by including code you can read on your own.
So since I'm not including code wholesale, I'll direct you to the two WSDAPI samples in the Windows SDK (StockQuote and FileService). I don't recall if generated code is included directly in the same (uhh...I feel like I should know that), but you can generate it easily enough from the included WSDLs.
That's great. Now how do I use all of this?
Alas, this is where things get beyond the scope of this article. Generated code is (on the surface) pretty simple stuff, so all you should need to use it is a basic understanding of the few fundamental WSDAPI control objects: specifically the IWSDDeviceProxy, IWSDServiceProxy, and IWSDDeviceHost. They're fairly straightforward and you probably won't have difficulty understanding them on your own, but you'll have to wait until the next installment of WSDAPI 101 if you want to hear what I've got to say about them.
So with that, see you next time!