Click here to Skip to main content
15,881,709 members
Articles / Desktop Programming / ATL
Article

XML Property Bag Implementation

Rate me:
Please Sign up or sign in to vote.
3.32/5 (12 votes)
1 Dec 20024 min read 125.6K   656   32   25
This is an ATL/COM-port of Don Box' excellent XML property bag implementation.

Introduction

First I'll assume you know COM. It wouldn't hurt to understand the concepts of serialization, nor does it hurt to have used the interfaces IPropertyBag and IPersistPropertyBag.

This is a port of Don Box' excellent XML property bag implementation. It's a COM class which implements the IPropertyBag interface, meaning that it can serialize and deserialize COM objects implementing the IPersistPropertyBag interface.

Property bags are essentially a collection of name/value pairs. When an object is serialized, the property bag basically asks the object to give it all its properties along with their names. Conversely, when an object is deserialized, the property bag asks the object to repopulate its properties using what's available in the property bag.

This information exchange is done through the interfaces IPropertyBag and IPersistPropertyBag. The property bag implements IPropertyBag and the serialized/deserialized object implements IPersistPropertyBag.

A serialization call sequence might look like this:

IPropertyBag::SaveToFile("file", pUnkObject);   
     |
     v
IPersistPropertyBag* pPersist;
pUnkObject->QueryInterface(
    IID_IPersistPropertyBag,
    &pPersist);
pPersist->Save(this, ...) --> IPersistPropertyBag::Save(IPropertyBag* pPropBag, ...)
                                                   |
                                                   v
                                         foreach(p in properties) {
IPropertyBag::Write(BSTR name,  <----  pPropBag->Write(p.bstrName, &p.varValue);
                    VARIANT* value)      }
    |
    v
Make data persistant (e.g. save to file)                                  

Ok, first I apologize for not drawing a proper picture, but I don't own a decent drawing program. Second, I'd like to inform you that it's in IPropertyBag::Write where the magic happens. Typically, it's here where data is made persistent. In this implementation, it generates an XML element inside an XML document which is written to disk after all properties have been saved.

IPropertyBag::Write can do more magic than meets the eye. If the variant it's been passed contains an interface pointer, it will be queried for the IPersistPropertyBag interface. If the query yields an interface pointer, it will be used recursively. Thus it is possible to serialize trees of objects.

Deserialization works similarly to serialization. IPersistPropertyBag::Read() is called instead of IPersistPropertyBag::Write(). The object being deserialized calls IPropertyBag::Read() instead of IPropertyBag::Write(). Not really hard at all.

IXMLPropertyBag

The implemented interface, besides IPropertyBag, contains only two methods:

[
    object,
    uuid(FC34FA47-86F7-4B19-88FA-43E073F29E14),
    dual,
    nonextensible,
    helpstring("IXMLPropertyBag Interface"),
    pointer_default(unique)
]
interface IXMLPropertyBag : IDispatch {
    // Serializes an object to an XML file
    [id(1)] HRESULT SaveToFile([in] BSTR bstrFileName, [in] IUnknown* pObject);
    [id(2)] HRESULT LoadFromFile([in] BSTR bstrFileName, 
        [in] IErrorLog* pErrorLog, [out,retval] IUnknown** ppObject);
};

The function LoadFromFile takes not only a file name and returns an object, it also takes an interface pointer to an error log object. This log is used when the deserialization process encounters errors.

Handled VARIANTs

This implementation can handle any variant except these:

  • which are by reference - VT_BYREF
  • which are arrays - VT_ARRAY
  • which cannot be transformed into strings - BSTR

Please note that user data types, VT_RECORD, are supported provided that type library information exists for that type.

Why use my code instead of Don Box'?

  • My code is compile and go. You get a ready to use DLL, while Don Box' implementation is really just a CPP file showing "This is how it can be done".
  • I believe I use less resources. Don Box' allocated a new property bag for each property which implemented IPersistPropertyBag. I don't do that, I use a stack where I store the XML element nodes instead, so that I can "backtrack".

Caveat Emptor

This software is far from complete and perfect. Here's a list of issues you should be aware of:

  • Property names cannot contain anything that would syntactically interfere with XML

    Property names are now mangled so that they never interfere with the XML syntax.

  • Property values cannot contain anything that would syntactically interfere with XML

    Maybe I should get a clue. Special XML characters are in fact escaped in text.

  • Source code looks like crap in other editors than mine.

    The reason is that Mr. Box uses spaces for tabbing, while I use the real McCoy. I may get around to beautify the code at some point.

  • Error log is not used

    Mr. Box never implemented error logging. I will most likely do it too once I find some implementation of IErrorLog.

  • XML is verbose

    XML may inflate your data quite a lot, and there is little you can do about it. The benefits of storing data as XML though is that you can use other tools to manipulate it and you can edit it by hand using a text editor.

License Grant

You are granted a license to use the code for whatever purpose, if and only if the following conditions are met: You may expect no warranties from my part. If you break something, you fix it. If we meet some day in the flesh, you may buy me a beer of my choice. This is not a requirement, but it would be a very nice thing to do and I would appreciate it. If your religion prohibits you from buying any alcohol, even if not for yourself, a coke is fine or whatever well testing beverage which you find morally and ethically acceptable.

Also, remember that portions of this code is copyright Don Box.

By the way, many thanks goes to Mr. Don Box for this excellent piece of code.

Revision history

  • 2002-12-02

    Initial version.

  • 2002-12-03

    Typos, bloody typos.

  • 2002-12-03

    XML text is escaped automagically with MSXML and most likely ActiveDOM too. So no special considerations are needed for property values.

  • 2002-12-05

    The property bag now mangle the property names so that they never mess up the XML syntax. Two new interface functions added: SaveToStream and LoadFromStream. Useful if you keep your XML property bags in structured storages for example.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Sweden Sweden
I make software.

Comments and Discussions

 
Questionre:biztalk server Pin
ambatiushasri17-Oct-06 19:42
ambatiushasri17-Oct-06 19:42 
AnswerRe: re:biztalk server Pin
Jörgen Sigvardsson17-Oct-06 21:46
Jörgen Sigvardsson17-Oct-06 21:46 
Questionerror 0x800A02E1 Pin
12hugs21-May-06 8:16
12hugs21-May-06 8:16 
AnswerRe: error 0x800A02E1 Pin
rambo0076-Sep-06 6:15
rambo0076-Sep-06 6:15 
QuestionSamples Please? Pin
Choppa13-Mar-03 6:34
Choppa13-Mar-03 6:34 
AnswerRe: Samples Please? Pin
Jörgen Sigvardsson13-Mar-03 11:09
Jörgen Sigvardsson13-Mar-03 11:09 
GeneralActiveX IpropertyBag: Get PARAM NAMES Pin
subramjobmail23-Feb-03 21:59
subramjobmail23-Feb-03 21:59 
GeneralRe: ActiveX IpropertyBag: Get PARAM NAMES Pin
andreshs18-May-03 21:59
andreshs18-May-03 21:59 
GeneralRe: ActiveX IpropertyBag: Get PARAM NAMES Pin
subramjobmail28-May-03 23:50
subramjobmail28-May-03 23:50 
GeneralRe: ActiveX IpropertyBag: Get PARAM NAMES Pin
andreshs11-Jun-03 23:59
andreshs11-Jun-03 23:59 
GeneralRe: ActiveX IpropertyBag: Get PARAM NAMES Pin
The Brett17-May-07 10:55
The Brett17-May-07 10:55 
GeneralI've got to see that Pin
Andreas Saurwein2-Dec-02 23:44
Andreas Saurwein2-Dec-02 23:44 
GeneralPoor swedish guys Pin
Jonathan de Halleux3-Dec-02 0:30
Jonathan de Halleux3-Dec-02 0:30 
GeneralRe: Poor swedish guys Pin
Andreas Saurwein3-Dec-02 5:24
Andreas Saurwein3-Dec-02 5:24 
GeneralRe: Poor swedish guys Pin
Jonathan de Halleux3-Dec-02 5:27
Jonathan de Halleux3-Dec-02 5:27 
GeneralRe: Snuss Pin
Hugo Hallman3-Dec-02 8:07
Hugo Hallman3-Dec-02 8:07 
GeneralRe: Snuss Pin
Jörgen Sigvardsson3-Dec-02 9:22
Jörgen Sigvardsson3-Dec-02 9:22 
GeneralRe: Snuss Pin
Jörgen Sigvardsson5-Dec-02 7:57
Jörgen Sigvardsson5-Dec-02 7:57 
GeneralRe: Poor swedish guys Pin
Beerfanatican2-Feb-03 21:11
sussBeerfanatican2-Feb-03 21:11 
GeneralRe: Poor swedish guys Pin
Jonathan de Halleux2-Feb-03 23:26
Jonathan de Halleux2-Feb-03 23:26 
GeneralRe: I've got to see that Pin
Jörgen Sigvardsson3-Dec-02 9:24
Jörgen Sigvardsson3-Dec-02 9:24 
QuestionDon Box Code? Pin
Rene De La Garza2-Dec-02 12:33
Rene De La Garza2-Dec-02 12:33 
AnswerRe: Don Box Code? Pin
Jörgen Sigvardsson2-Dec-02 21:59
Jörgen Sigvardsson2-Dec-02 21:59 
AnswerRe: Don Box Code? Pin
Jörgen Sigvardsson2-Dec-02 22:06
Jörgen Sigvardsson2-Dec-02 22:06 
GeneralRe: Don Box Code? Pin
Rene De La Garza3-Dec-02 10:04
Rene De La Garza3-Dec-02 10:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.