COM组件对象如何实现索引属性
2009-07-06 08:17
495 查看
在前面的系列文章中,我们知道了如何实现javascript和COM对象之间的互操作。在这里,我们再来看一个特殊的应用--索引属性。索引属性,就是让COM对象可以象一个数组一样的访问。比如,我们有一个COM对象实例oMyArray,在javascript中可以这样调用:
缺省属性很好实现,就是让COM对象提供一个DISPID=0的属性方法即可。
索引属性,就需要重载 IDispatch接口的GetIDsOfNames和Invoke方法。
我们先看看javascript是如何执行索引属性的。
javascript遇到oMyArray[0]时,调用IDispatch.GetIDsOfNames方法,查看是否存在名称为“0”的属性。如果存在,就用返回的DISPID继续调用IDispatch.Invoke方法。
为了方便起见,在下面的示例中,只支持long型的索引参数。
//标准方式 oMyArray.item(0)="test"; alert(oMyArray.item(0)); //缺省属性的方式 oMyArray(0)="test"; alert(oMyArray(0)); //索引属性的方式 oMyArray[0]="test"; alert(oMyArray[0]);
缺省属性很好实现,就是让COM对象提供一个DISPID=0的属性方法即可。
索引属性,就需要重载 IDispatch接口的GetIDsOfNames和Invoke方法。
我们先看看javascript是如何执行索引属性的。
javascript遇到oMyArray[0]时,调用IDispatch.GetIDsOfNames方法,查看是否存在名称为“0”的属性。如果存在,就用返回的DISPID继续调用IDispatch.Invoke方法。
为了方便起见,在下面的示例中,只支持long型的索引参数。
__interface IMyArray : IDispatch { [id(00000000), propget] HRESULT Item([in] VARIANT VarKey,[out, retval] VARIANT* pvar); [id(00000000), propput] HRESULT Item([in] VARIANT VarKey,[in] VARIANT pvar); class ATL_NO_VTABLE CMyArray : public IDispatchImpl<IMyArray> { public: HRESULT FinalConstruct() { m_nIndexCounter=10000; } private: //方便起见,仅支持long型的索引名 CAtlMap<long,_variant_t> m_oMapFromNameToValue; //支持索引式的访问 DISPID m_nIndexCounter; CAtlMap<DISPID,long> m_oMapFromIdToIndex; CAtlMap<long,DISPID> m_oMapFromIndexToId; public: //支持缺省属性 STDMETHOD(get_Item)(VARIANT VarKey,VARIANT* pvar); STDMETHOD(put_Item)(VARIANT VarKey,VARIANT pvar); //支持索引属性 STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid); STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr); }; ///////实现 STDMETHODIMP CMyArray::get_Item(VARIANT VarKey,VARIANT* pvar) { // _variant_t vResult; m_oMapFromNameToValue.Lookup(VarKey.lVal,vResult); *pvar=vResult.Detach(); return S_OK; } STDMETHODIMP CMyArray::put_Item(VARIANT VarKey,VARIANT pvar) { // m_oMapFromNameToValue.SetAt(VarKey.lVal,pvar); return S_OK; } STDMETHODIMP CMyArray::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid) { // HRESULT hr=__super::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if(hr!=DISP_E_UNKNOWNNAME) return hr; //作为索引属性来使用 long nIndex=_wtol(rgszNames[0]); DISPID nDispId; if(this->m_oMapFromIndexToId.Lookup(nIndex,nDispId)) { *rgdispid=nDispId; } else { nDispId=++m_nIndexCounter; this->m_oMapFromIdToIndex.SetAt(nDispId,nIndex); this->m_oMapFromIndexToId.SetAt(nIndex,nDispId); *rgdispid=nDispId; } // return S_OK; } STDMETHODIMP CMyArray::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr) { //可以先判断是否为索引属性,因为索引属性是从10000开始的,不会冲突 long nIndex; if(this->m_oMapFromIdToIndex.Lookup(dispidMember,nIndex)) { if(wFlags & DISPATCH_PROPERTYGET) { return this->get_Item(_variant_t(nIndex),pvarResult); } else if( ( (wFlags & DISPATCH_PROPERTYPUT) || (wFlags & DISPATCH_PROPERTYPUTREF) ) && pdispparams->cArgs==1 ) { return this->put_Item(_variant_t(nIndex),pdispparams->rgvarg[0]); } else { return E_FAIL; } } else { return __super::Invoke( dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); } }
相关文章推荐
- ReportView 如何实现按页码控制报表对象的显示属性
- matlab中如何实现对不同类型对象(类型也可相同)的索引?(很重要的用法)
- 如何实现单例的进程内COM组件
- HreoWinGauge2.0组件集应用示例----在应用程序中如何快速引用对象和属性
- 如何实现返回记录集的 Visual C++ COM 对象
- 如何在SpringMVC框架中利用Java反射机制和Javassist实现Java对象、属性、注解的动态创建生成
- js对象如何实现数组索引功能并且自定义自己的方法 (4种方法)
- 转:ECharts图表组件之简单关系图:如何轻松实现另类站点地图且扩展节点属性实现点击节点页面跳转
- ECharts图表组件之简单关系图:如何轻松实现另类站点地图且扩展节点属性实现点击节点页面跳转
- ECharts图表组件之简单关系图:如何轻松实现另类站点地图且扩展节点属性实现点击节点页面跳转
- UnityEditor 如何将一个资源文件夹下的对象拖曳赋值到文件夹外的某个对象组件属性中
- 如何对List集合中的对象进行按某个属性排序
- 浅谈javascript对象、如何实现继承、jQuery方法的扩展(jquery插件)
- 如何通过实现parcelable接口传递值对象
- 如何实现一个php组件
- 如何给你的json对象的某个方法,然后用这个对象的属性输出结果?
- js如何判断一个对象是array ,instanceof 是基于什么实现的呢?
- 如何保证Java对象内部属性的不可变状态
- Dozer 实现对象间属性复制
- 这是我学习COM遇到的几个基本问题其解决 黄森堂(vcmfc)著 1.我用ATL生成一个组件对象,我在COM中使用IDD_IEncrypt,这个在哪里写义,是啥?GUID? 答:IDD_IEncry