In c++ we can easily set up method chaining in a class by designing methods returning *this. Would this be possible in an ATL/COM setting ? Let's say I have a simple ATL class MyOBj. I would like to know if chaining is possible in this context, and if so, what would be the idl signature of the method that would support chaining ? Simple examples would be appreciated ! (In fact, my methods are called from VBA for excel, and I would like to have chaining in that VBA context, as we have chaining already for standard VBA methods.)
Thx a lot
R
EDIT :
In the .idl file I have this :
interface IRateModel : IDispatch{
[id(1), helpstring("SETRATEMODEL")] HRESULT SETRATEMODEL( [in] VARIANT * var_in ) ;
[id(2), helpstring("GETRATETERMSTRUCTURE")] HRESULT GETRATETERMSTRUCTURE( [in, out] VARIANT * var_in ) ;
};
interface IVolatilityModel : IDispatch{
[id(1), helpstring("SETVOLATILITYMODEL")] HRESULT SETVOLATILITYMODEL( [in] VARIANT * var_in ) ;
[id(2), helpstring("GETVOLATILITY")] HRESULT GETVOLATILITY( [in, out] VARIANT * var_in ) ;
};
interface IMyOption : IDispatch{
[id(1), helpstring("SETMATURITY")] HRESULT SETMATURITY( [in] VARIANT * TheMaturity, [out,retval] IMyOption ** ret ) ;
[id(2), helpstring("SETSTRIKE")] HRESULT SETSTRIKE( [in] VARIANT * TheStrike, [out,retval] IMyOption ** ret ) ;
[id(3), helpstring("SETPAYOFF")] HRESULT SETPAYOFF( [in] VARIANT * ThePayoff, [out,retval] IMyOption ** ret ) ;
[id(4), helpstring("ATTACHRATEMODEL")] HRESULT ATTACHRATEMODEL( [in] IRateModel ** TheRateModel, [out,retval] IMyOption ** ret ) ;
[id(5), helpstring("ATTACHVOLATILITYPROCESS")] HRESULT ATTACHVOLATILITYPROCESS( [in] IVolatilityModel ** TheVolatilityModel, [out,retval] IMyOption ** ret ) ;
[id(6), helpstring("PRICEIT")] HRESULT PRICEIT( [in, out] DOUBLE * price ) ;
};
SETRATEMODEL's implementation is :
STDMETHODIMP CRateModel::SETRATEMODEL( /*[in]*/ VARIANT * var_in )
{
// something
// ...
return S_OK ;
}
This implementation hasn't changed since I added other interface. Before adding them, at debug, the VARIANT was as VT_R8 (coming from a vba VARIANT, this one coming from an excel's double) Now at debug, the variant is a VT_DISPATCH.
PS : I'm a very fresh-starter in ATL/COM.
Following Igor Tandetnik first answer, I've tried chaining methods for ATL/COM as follows, in simple ATL/COM object called "Complex", modelling complex numbers :
in the IDL file :
in the Complex.h file :
In the Complex.cpp file :
// Complex.cpp : Implementation of CComplex
MyVARIANT is a VARIANT wrapper class, that works perfectly and that as been fully backtested. In
GET fills the ATL::CComVariant myccomvarx with the coeff (0,0) of the MyVARIANT myvarx.
One can easily guess what
and
methods are doing. In
the method ATTACH "fills" the VARIANT var_out with the MyVARIANT "module" constructed by the constructor
which assciates (in this case) a MyVARIANT to a pointer to double. Let me say again that MyVARIANT has been fully backtested, and that it fully works.
Now, on the VBA for Excel side, I created the six following functions :
I called each of these six functions F (that, F is equal to calcmodule11, or calcmodule12, or... etc) in a excel cell, writing
in it, where B3 and B4 are two excel cells containing each the double 1. Here are the results obtained for each function :
calcmodule11 #VALUE! calcmodule12 1.414213562 calcmodule21 1.414213562 calcmodule22 #VALUE! calcmodule31 #VALUE! calcmodule32 #VALUE!
1.414213562 is indeed the right value expected.
Questions :
1) Why do I have a #VALUE! for the call to calcmodule11 ?
2) As calcmodule12 gives the right value and calcmodule11 not, I would expected the same behaviour for the pair (calcmodule21, calcmodule22), but it is the contrary : calcmodule21 gives the right value, and calcmodule22 not. Why ?
2) As Igor Tandetnik explained it its first answer to my question, I put method chaining in place in functions calcmodule31 and calcmodule32. And it doesn't work, where it work in the calcmodule21 and calcmodule22 case, at least for calcmodule21. Why ?
Igor Tandetnik, as I put in place exactly what you advised to me (correct me if I'm wrong), why doesn't it work ?...
Thx a lot.
Ok, the #VALUE! is caused in function calcmodule11 because what is passed to it as VARIANT isa "VARIANT/Object/Range" whose value2 component is a VARIANT/double, and I'm not handling VARIANT/Object/Range in my MyVARIANT wrapper class. But if y pass x.value2 (in vba) do the method, everything's fine. This explain also why the trick dim xx as variant, xx = x functions : do this somehow puts in xx the x.value2, but I dont know why... For the #VALUE! in VBA functions involving method chaining, the reason is the same, except that the VARIANT is even more complex : a pointer to a com obj instance...
Therefore, I will have to rewrite/complete my MyVARIANT class to handle all cases of VT_DISPATCH that will arise, as "VARIANT/Object/Range", but also more complexes other VT_DISPATCH'es...
Something like this:
Scripting clients should be able to do
myObj.DoSomething(42).DoSomethingElse()