IDispatchImpl2 Class Template Reference
[COM Automation Library]

#include <atlstl/automation/multiple_dispatch.hpp>

List of all members.


Detailed Description

template<typename I0, IID const * IID0, typename I1, IID const * IID1, GUID const * LibID>
class atlstl::IDispatchImpl2< I0, IID0, I1, IID1, LibID >

Class template that enables the methods and properties exhibited through two IDispatch interfaces to be visible to scripting clients.

The class template is used in place of ATL's IDispatchImpl class in the parent class list of a class template that support two dispinterfaces. Consider the Open-RJ COM mapping's Field class [IDL]:

  // openrj.com.idl
  [ . . . ]
  interface IField
    : IDispatch
  {
    [propget, id(1), . . .]
    HRESULT Name([out, retval] BSTR* pVal);
    [propget, id(2), . . .]
    HRESULT Value([out, retval] BSTR* pVal);
  };

  [ . . . ]
  interface IDocumenter
    : IDispatch
  {
    [propget, id(1), . . .]
    HRESULT DocString([out, retval] BSTR* pVal);
  };

  coclass Field
  {
    [default] interface IField;
    interface IDocumenter;
  };
As indicated, it supports two dispinterfaces: IField and IDocumenter. Note that each interface has a property with dispid 1.

By default, the ATL class template IDispatchImpl assumes that just a single "active" dispinterface. We might envisage the following (C++) class definition for Field:

  class ATL_NO_VTABLE Field
    : public CComObjectRootEx<CComSingleThreadModel>
    , public CComCoClass<Field, &CLSID_Field>
    , public atlstl::SupportErrorInfoImpl<&IID_IField>
    , public IDispatchImpl<IField, &IID_IField, &LIBID_OPENRJ_COMLib>
    , public IDispatchImpl<IDocumenter, &IID_IDocumenter, &LIBID_OPENRJ_COMLib>
  {
    . . .
  };
Unfortunately, scripting clients, which elicit DISPIDs at runtime via an automation server's IDispatch::GetIDsOfNames() method, will see only those methods and properties from IField in such a case. No parts of the IDocumenter interface will be visible or accessible.

This is where IDispatchImpl2 comes in. It implements GetIDsOfNames() and Invoke(), operating over both its dispinterfaces to elicit the dispid(s) for requested name(s) by querying each interface in turn. It is used with the Field class as follows:

  class ATL_NO_VTABLE Field
    : public CComObjectRootEx<CComSingleThreadModel>
    , public CComCoClass<Field, &CLSID_Field>
    , public atlstl::SupportErrorInfoImpl<&IID_IField>
    , public atlstl::IDispatchImpl2<IField, &IID_IField, IDocumenter, &IID_IDocumenter, &LIBID_OPENRJ_COMLib>
  {
    . . .
  };

Now all members of all dispinterfaces are visible to scripting clients. Note that the class also handles the case where the dispinterfaces have members/properties with the same dispids. (See GetIDsOfNames() and Invoke() for details of the mechanism.)

Public Types

Member Types
typedef IDispatchImpl< I0,
IID0, LibID > 
dispatch_parent_0_type
 The type of the first dispinterface.
typedef IDispatchImpl< I1,
IID1, LibID > 
dispatch_parent_1_type
 The type of the second dispinterface.

Protected Member Functions

IDispatch methods
HRESULT GetIDsOfNames (REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
 Provides the required behaviour of IDispatch::GetIDsOfNames(), by querying the two dispinterfaces, in order, to match the name(s).
HRESULT Invoke (DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
 Provides the required behaviour of IDispatch::Invoke(), by invoking this method on the requisite dispinterface.


Member Typedef Documentation

typedef IDispatchImpl<I0, IID0, LibID> dispatch_parent_0_type

The type of the first dispinterface.

typedef IDispatchImpl<I1, IID1, LibID> dispatch_parent_1_type

The type of the second dispinterface.


Member Function Documentation

HRESULT GetIDsOfNames ( REFIID  riid,
LPOLESTR *  rgszNames,
UINT  cNames,
LCID  lcid,
DISPID *  rgdispid 
) [inline, protected]

Provides the required behaviour of IDispatch::GetIDsOfNames(), by querying the two dispinterfaces, in order, to match the name(s).

This method operates by first determining which, if any, of the two parent dispinterfaces can resolve the names. If successful, the resultant dispatch Ids are then striped with a bit in their most-significant byte(s) to record the index of the dispinterface which has thus undertaken to interpret them. This stripe is then detected

Remarks:
Names are matched en bloc: they are either all matched by one interface, or all by the other. It is never the case that some part are matched by one and the remainder by the other.
Note:
If a dispid returned from a successful call to one of the underlying dispinterfaces' GetIDsOfNames() already uses the striping bit, it is left alone. Such methods will be successfully called in Invoke(), in its post-stripe processing.

References ATLSTL_MESSAGE_ASSERT.

HRESULT Invoke ( DISPID  dispidMember,
REFIID  riid,
LCID  lcid,
WORD  wFlags,
DISPPARAMS *  pdispparams,
VARIANT *  pvarResult,
EXCEPINFO *  pexcepinfo,
UINT *  puArgErr 
) [inline, protected]

Provides the required behaviour of IDispatch::Invoke(), by invoking this method on the requisite dispinterface.

This method operates by detecting the striping bit on the dispid, from which the appropriate dispiniterface is determined. The stripe is then removed, and the method invoked.

Remarks:
Names are matched en bloc: they are either all matched by one interface, or all by the other. It is never the case that some part are matched by one and the remainder by the other.
Note:
If no striping is apparent, the invocation is conducted on each interface in turn.


The documentation for this class was generated from the following file:

Generated on Thu Jun 10 08:58:23 2010 for STLSoft by  doxygen 1.5.6