COM+ allows you to pass a construction parameter to new instances of your component. This instance activation service has nothing to do with application scalability, JITA, or object pooling, and is nothing more than a neat service.
On your component’s Properties page, there is a properties
group named “Object construction” on the Activation tab.
Once you enable this service (by checking the “Enable object
construction” checkbox), you can specify a string in free form.
Every instance of your component has access to this one string (you
cannot specify a string per instance). Because calls to
CoCreateInstance( )
or CreateObject( )
do not accept initialization parameters, you have to work
to gain access to the constructor string.
The first thing you need to do (besides enable the service) is have
your component implement an interface called
IObjectConstruct
, defined as:
interface IObjectConstruct : IUnknown { HRESULT Construct([in]IDispatch* pConstructionObj); };
If you enable object construction but do not implement the interface,
all client attempts to create a new instance of your component will
fail, showing the error code
E_NOINTERFACE
. They will fail because COM+ will
refuse to hand over to the client an object that could not be
initialized properly. IObjectConstruct
has only
one method, Construct( )
,
which COM+ uses to pass in a pointer to another interface called
IObjectConstructString
, defined as:
interface IObjectConstructString : IDispatch { [id(1),propget] HRESULT ConstructString([out, retval] BSTR* pVal); };
COM+ calls your object’s implementation of
IObjectConstruct::Construct( )
to deliver the
string only once, immediately after calling the object constructor.
Note that COM+ passes the construction string to your object before
the call to IObjectControl::Activate( )
, since the
initialization parameter should provide generic, rather than
context-specific, information.
Example 3-2 shows how to use the constructor string
object passed into IObjectConstruct::Construct( )
to access your component’s configured constructor string.
Example 3-2. Implementing IObjectConstruct::Construct( ) and accessing your component’s configured constructor string
// IObjectConstruct::Construct( ) STDMETHODIMP CMyComponent::Construct(IDispatch * pConstructionObj) { HRESULT hres = S_OK; BSTR bstrConstruct; IObjectConstructString* pString = NULL; hres = pConstructionObj->QueryInterface(IID_IObjectConstructString, (void**)&pString); hres = pString->get_ConstructString(&bstrConstruct); pString->Release( ); //Use bstrConstruct return S_OK; }
Note that empty strings may be valid parameters and that your object should be written to handle an empty string.
However, why go through a somewhat odd mechanism of retrieving the
string from a dedicated interface, rather than passing
IObjectConstruct::Construct( )
a
BSTR
directly? The answer is that in the future,
COM+ may allow you to pass other kinds of parameters for
construction, such as numbers, data structures, or maybe even
interface pointers. The COM+ designers wanted to put in place a
generic mechanism that could extend to handling more than just
strings.
You can use a construction string to specify parameters common to all components, but whose value is deployment specific, such as:
Log filename and location. The COM+ logbook, presented in Appendix A, uses the constructor string to do just that.
Application or component configuration filename and location.
If your component holds a generic ODBC connection, you can specify a DSN file name—referencing a file containing information about the database to be used by this component—instead of either passing it in as a method parameter or hardcoding it.