IUnknow IDispatch IInspectable QueryInterface

IUnknow接口是个伟大的创造!
 
 IUnknow的AddRef和Release实现对象的引用计数管理, 引用计数用来管理对象的生存周期。
通过引用计数一来可以很方便的共享对象, 另外也能确保对象被正确释放(确保对象的new和delete在同一模块中)。
 
QueryInterface实现接口查询, 通过这种方式可以很方便的对现有组件进行升级, 只要接口不改 ,可以随意修改内部实现而不用客户程序重新编译。
另外也可以直接增加新接口, 只要在QueryInterface内增加并可以查询到该新接口, 我们就可以调用该新接口。
 
我们可以看到QueryInterface让C++这种静态语言有了某些动态语言的特性, 在C# 中我们可以通过反射查询到某个类的成员函数和成员变量, Objective-C中我们也可以根据函数名动态调用某个函数, 在脚本语言中,我们可以在运行时动态查询和修改某个类的信息。通过COM的QueryInterface, 我们可以动态查询某个组件类实现哪些接口(函数)。当然他们之间有本质的区别, 动态语言运行时内存中保存有类信息, 而C++的QueryInterface通过switch case, 返回的是存有虚表指针的对象指针。
 
最后再简单谈下IUnknown的升级版IDispatch和IInspectable。


先看IDispatch: 

    IDispatch :  public  IUnknown
    {
    
public :
        
virtual  HRESULT STDMETHODCALLTYPE GetTypeInfoCount( 
            
/*  [out]  */  __RPC__out UINT  * pctinfo)  =   0 ;
        
        
virtual  HRESULT STDMETHODCALLTYPE GetTypeInfo( 
            
/*  [in]  */  UINT iTInfo,
            
/*  [in]  */  LCID lcid,
            
/*  [out]  */  __RPC__deref_out_opt ITypeInfo  ** ppTInfo)  =   0 ;
        
        
virtual  HRESULT STDMETHODCALLTYPE GetIDsOfNames( 
            
/*  [in]  */  __RPC__in REFIID riid,
            
/*  [size_is][in]  */  __RPC__in_ecount_full(cNames) LPOLESTR  * rgszNames,
            
/*  [range][in]  */  UINT cNames,
            
/*  [in]  */  LCID lcid,
            
/*  [size_is][out]  */  __RPC__out_ecount_full(cNames) DISPID  * rgDispId)  =   0 ;
        
        
virtual   /*  [local]  */  HRESULT STDMETHODCALLTYPE Invoke( 
            
/*  [in]  */  DISPID dispIdMember,
            
/*  [in]  */  REFIID riid,
            
/*  [in]  */  LCID lcid,
            
/*  [in]  */  WORD wFlags,
            
/*  [out][in]  */  DISPPARAMS  * pDispParams,
            
/*  [out]  */  VARIANT  * pVarResult,
            
/*  [out]  */  EXCEPINFO  * pExcepInfo,
            
/*  [out]  */  UINT  * puArgErr)  =   0 ;
        
    };

 

IDispatch继承于IUnknown, 通过IDispatch, 我们可以实现脚本语言对COM组件的调用,我们可以通过GetTypeInfo获取对象的类型信息, 通过GetIDsOfNames函数以字符串的方式获取函数的DISPID, 通过Invoke动态调用某个函数。IE的DOM对象与JS的交互全部是通过IDispatch(Ex)接口实现的。当然,除非你的组件要与脚本语言交互, 否者一般不用实现该接口。
 
再看IInspectable: 
    IInspectable :  public  IUnknown
    {
    
public :
        
virtual  HRESULT STDMETHODCALLTYPE GetIids( 
            
/*  [out]  */  __RPC__out ULONG  * iidCount,
            
/*  [size_is][size_is][out]  */  __RPC__deref_out_ecount_full_opt( * iidCount) IID  ** iids)  =   0 ;
        
        
virtual  HRESULT STDMETHODCALLTYPE GetRuntimeClassName( 
            
/*  [out]  */  __RPC__deref_out_opt HSTRING  * className)  =   0 ;
        
        
virtual  HRESULT STDMETHODCALLTYPE GetTrustLevel( 
            
/*  [out]  */  __RPC__out TrustLevel  * trustLevel)  =   0 ;
        
    };

 

IInspectable也继承于IUnknown, 它是WinRT所有对象的基接口, 所以WinRT还是基于COM技术。
其中GetTrustLevel返回信任等级, GetRuntimeClassName返回类名, 而GetIids返回当前类对象实现了哪些接口(所有接口的iid), 得到接口的iid后, 我们就可以通过QueryInterface查询我们需要的接口了, 得到接口指针就可以调用内部函数了。
 
最后总结下,回答下文章开头的问题, 很多人说COM过时了, 也许”纯正的标准COM“确实是使用的人越来越少了, 但是COM的思想却一直在后续的软件开发中被使用和发扬, 可以说COM技术是微软技术框架的“根”(之一)。
posted on 2014-03-14 09:11  提里奥弗丁 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/Fordring/p/3599803.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值