#include <atlstl/automation/multiple_dispatch.hpp>
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; };
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> { . . . };
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. |
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.
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
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.