one of the thousands of programmers out there writing server-side
business components, then youve probably used data wrappers:
light-weight objects designed to access streamed data. The
following article builds on the traditional wrapper concept to create
self-aware objects, which offer the added benefits of simplicity and
As any good component programmer will
tell you, it is always important to minimize the number of calls
between objects; and one of the ways we achieve this is to pack all
of our data up into "streams" to pass it from one object to another.
Instead of passing, say CustomerID, Name, and Email as separate
properties, we wrap them up into a single string; perhaps an XML
stream, like so:
Often the easiest
way to manage these strings in our code, is by writing a
data-wrappera custom class, which gives access to all the
pieces of data through COM properties: objCustomer.CustomerID,
objCustomer.Email, and so on.
However, we also know that data wrappers
can be a pain to writestream and un-stream methods are fiddly
(do this property, so that property, do the other property), and
you have to re-write them from scratch every time, often by cutting
and hacking code from similar objects elsewhere in the system.
What a drag. Wouldnt it be nice if we could write a data wrapper
once, and then re-use it in a variety of scenarios, with only minimal
"two-minute" modifications? This article shows you how.
The solution is to write an object that
discovers its own properties. That way, your stream and un-stream
methods only have to be written once, and then you just add or
remove properties to create exactly the wrapper you need. The
solution uses a little-documented Win32 objectthe Type Library
Information component: TLBINF32.dll.
The Type Library Information component,
which, if its not in your System32 directory, can be found on your
Visual Basic 6 CD, provides some neat methods to explore the
public interface of any COM object at run time. Try thinking of it as
accessing VBs Object Browser in your code!
Its InterfaceInfoFromObject method
exposes a Members collection, which will permit us to loop through
all the membersi.e. public properties, methods and variables
of our object; and we will use it in our stream/ un-stream methods
to loop though all of the properties of our wrapper one by one.
My example project references
two external libraries: the MS XML object, to "stream" our
wrapper to XML; and the Type Library Information component, to
"discover" the public interface of our wrapper.
First of all we need
some public properties for our wrapper, which express the
attributes of our data.
I have created a
simple class, and added three public variables.
Now, a traditional "stream" method for this
object would look a little like this pseudo-code.
Stream = Stream & Me.CustomerID
Stream = Stream & Me.Name
Stream = Stream & Me.Email
But I am going to
write a stream method which loops through all of the properties,
however many there are, and whatever their names, and packs
them up into XML. The code below uses the Type Library
Information object (TIL), which exposes all the public properties of
the object (Me) as a collection of Members. As we loop through the
Members collection (using a For Each construct), we expose the
Name of each public variable in our class (objMember.Name)
ContactID, Email, etc.
We can then use VBs CallByName
function to get the value of each of our public variables. You can
find documentation about CallByName in the VB help files, but
basically it is an alternative way of invoking an objects public
properties, akin to late-binding with CreateObject.
S = CallByName (Me, "ContactID", vbGet)
Is analogous to:
S = Me.ContactID
retrieved the value of the property, using CallByName, we use the
XML object to append a node to a local document, which we will
stream-out just before we exit the method.
And the un-stream
method works the exact same waylooping through all of the
members of the wrapper, and invoking the method by name to set
Now I can do
two things. I can continue to add more public variables to
my class, and (without any extra work) they will be streamed and
un-stream along with everything else. And, second, I can copy my
XML property statements (my custom stream and un-stream
methods) to a new class, to which I can add different variables,
referencing a completely different part of the system: Orders, say,
and I have a brand-new wrapper class in seconds.
Lets look at a concrete example.
Ill begin with the wrapper class described
above. It has properties of CustomerID, Name and Email. As a
new customer is entered at the user interface, an instance of our
wrapper (XMLCustomer) is created, and each property is
MyBusinessObject, the SaveCustomer method reconstructs the
wrapper object from the XML stream, and validates and saves the
Now, say I am
asked to add a new item to our customer dataCountry, for
example. All I need do is go to my wrapper, and add the additional
item as a new public variable.
Now I can
reference this variable in all of my UI code, without any troubles at
all, and it will be automatically included in the XML stream that is
passed through to my business object.
As you can see,
these data wrappers are easy to create, and even easier to
maintain. Of course, we must be aware that these kinds of
techniques have their limitations. There is always a performance hit
when running additional external objects; and it is not
recommended to deal with very large documents, or hierarchical
objects in this manner. Nevertheless, I hope these techniques
inspire you to try something different in you coding
Contact Syd at sydneye@com
ponentsource.com or at
Component Source - The Definitive Source of Software