Examples

The following is some code in Visual Basic that illustrates the usage of the SFL property bag implementations.

Initializing and loading an object from an XML property bag

Set bag = New XMLPropertyBag

bag.Init "books.xml"

bag.Load "BooksCollection", Books

bag.Commit

 

Saving an existing object to a registry property bag

Set bag = New RegistryPropertyBag

bag.Init "Software\Stingray\SFL\Persistence"

bag.Save "BooksCollection", Books

bag.Commit

 

The implementation of the persistable object in Visual Basic requires the class to be marked as Persistable, by assigning the corresponding value to the class properties. This adds two methods to the class, ReadProperties() and WriteProperties(), which correspond to the Load() and Save() methods of the IPropertyBag interface. Implementing Load() and Save() methods for a collection class shows the implementation of these methods for a book collection class.

Implementing Load() and Save() methods for a collection class

Private Sub Class_ReadProperties(PropBag As PropertyBag)

Dim count As Integer

count = PropBag.ReadProperty("BooksCount")

ReDim Books(1 To count)

Dim i As Integer

For i = 1 To count

Set Books(i) = PropBag.ReadProperty("Book" & i)

Next i

End Sub

 

Private Sub Class_WriteProperties(PropBag As PropertyBag)

Dim count As Integer

count = UBound(Books)

PropBag.WriteProperty "BooksCount", count

Dim i As Integer

For i = 1 To count

PropBag.WriteProperty "Book" & i, Books(i)

Next i

End Sub

 

To implement a persistable object in C++, you need to implement one of the COM interfaces IPersistPropertyBag or IPersistPropertyBag2. How to do this depends on the framework you are using to develop your components. Implementing a persistable C++ object using ATL shows what it might look like if you used ATL.

Implementing a persistable C++ object using ATL

class CPersistableComponent:

public CComObjectRootEx<CComSingleThreadModel>,

public CComCoClass<CPersistableComponent, &__uuidof(CPersistableComponent)>,

public IMyComponent,

public IPersistPropertyBag

{

public:

BEGIN_COM_MAP(CPersistableComponent)

COM_INTERFACE_ENTRY(IPersistPropertyBag)

COM_INTERFACE_ENTRY2(IPersist, IPersistPropertyBag)

COM_INTERFACE_ENTRY(IMyComponent)

END_COM_MAP()

º

};

It is important to notice that persistable COM objects need to be creatable, since the property bag needs to create a new instance using the standard COM mechanisms whenever it is retrieving an object of that class. To be created, an object requires a CLSID and a registered class factory.

Implementing Save() and Load() methods for a persistable C++ object shows the implementation of the Save() and Load() methods of a persistable object. The implementation makes use of the Load() and Save() methods in the IPropertyBag (or IPropertyBag2) interface pointer it receives as a parameter to retrieve or store individual pieces of data the object considers to be part of its persistent internal state.

Implementing Save() and Load() methods for a persistable C++ object

STDMETHOD(Load)(IPropertyBag* pPropBag, IErrorLog* pErrorLog)

{

HRESULT hr = S_OK;

_variant_t vaProp;

hr = pPropBag->Read(OLESTR("Number"), &vaProp, pErrorLog);

if (FAILED(hr)) return E_FAIL;

m_nANumber = static_cast<long>(vaProp);

vaProp.Clear();

 

CPoint pt;

hr = pPropBag->Read(OLESTR("PositionX"), &vaProp, pErrorLog);

if (FAILED(hr)) return E_FAIL;

pt.x = static_cast<long>(vaProp);

hr = pPropBag->Read(OLESTR("PositionY"), &vaProp, pErrorLog);

if (FAILED(hr)) return E_FAIL;

pt.y = static_cast<long>(vaProp);

 

return S_OK;

}

 

STDMETHOD(Save)(IPropertyBag* pPropBag, BOOL fClearDirty,

BOOL fSaveAllProperties)

{

HRESULT hr = S_OK;

_variant_t vaProp;

vaProp = static_cast<long>(m_nANumber);

hr = pPropBag->Write(OLESTR("Number"), &vaProp);

if (FAILED(hr)) return E_FAIL;

vaProp = static_cast<long>(m_rc.left);

hr = pPropBag->Write(OLESTR("PositionX"), &vaProp);

if (FAILED(hr)) return E_FAIL;

vaProp = static_cast<long>(m_rc.top);

hr = pPropBag->Write(OLESTR("PositionY"), &vaProp);

if (FAILED(hr)) return E_FAIL;

return S_OK;

}