后邦定
VB中后邦定
dim objMath as Object
Dim nResult as Integer
Set objMath =CreateObject("Chapter6.Math")
nResult=objMath.Add(100,55)
Set objMath=Nothing
在Visual Basic 中,Object类型保存了一个IDispatch指针,且CreateObject例程可以创建一个有ProgID指定的组件的实例
c++中中后邦定
CLSIDFromProgID("Chapter6.Math",&clsid);
IDispatch pDispatch=0;
CoCreateInstance(clsid,
...
IID_IDispatch,
(void**)&pDispatch);
DISPID dispid;
pDispatch->GetIDsOfNames("Add",&dispid);//将add映射为dispid
pDispatch->Invoke(dispid,parameters,&result,...);//dispid被映射为派发表中一个确切的偏移量,用来确定哪个接口方法被调用
pDispatch->Release();
实现IDispatch接口
如果一个接口通过IDispatch接口向外公开它的功能,则它被看作一个automation component(自动化组件)
只实现IDispatch接口的组件只能提供派发接口
声明一个派发接口
[
uuid(0D17C2EA-0D1B-49B8-8D0E-23AE05F14FA8),
helpstring("DMath dispointerface")
]
dispionterface DMath
{
properties:
methods:
[id(1)] long Add(long lOp1,lOp2);
};
....
coclass Math
{
[default] dispionterface DMath;
};
可以用IDL来描述相同的接口
[
object,
uuid(0D17C2EA-0D1B-49B8-8D0E-23AE05F14FA8),
helpstring("IMath Idispointerface")")
]
interface IMath : IDispatch
{
[id(1), helpstring("method Add")] HRESULT Add([in] VARIANT varOp1,[in] VARIANT varOp2,[out,retval] ARIANT* pvarResult) ;
};
....
coclass Math
{
[default] interface IMath;
};
访问基于IDispatch的接口
对于派发接口或双向接口的客户程序,有许多选项涉及它如何邦定到一个自动化组件的功能。
如果组件只实现派发接口,并且不提供类型库,后邦定是唯一的选项
如果组件实现派发接口,并且提供类型库,组件可以选择后邦定和被称为ID的邦定
如果组件实现双向接口,并且提供类型库,组件可以选择后邦定,ID的邦定和前邦定之间选择
后邦定(动态邦定)
客户机程序在运行时决定组件的功能
客户机程序的开发阶段并不对方法的名字和参数类型进行检查,相反,组件的功能只有在运行时才被申请并调用
也就是说,客户机程序首查询DISPID的方法,然后构造DISPPARAMS结构,接着通过IDispatch接口调用Invoke方法
工作量大,灵活性高,如果服务器接口发生变化,则客户机程序不用重新编译就可以从服务器接口的新增特性中受益
VB中的后邦定例子
Dim objMath as Object
Dim nResult as Integer
Set objMath =CreateObject("Chapter6.Math")
nResult=objMath.Add(100,55)
Set objMath=Nothing
c++中的后邦定例子
IDispatch *pDispatch;
HRESULT hr=CoCreateInstance(CLSID_Math,
NULL,
CLSCTX_SERVER,
IID_IDispatch,
(void**)&pDispatch);
if(FAILED(hr))
{..}
LPOLESTR lpOleStr=L"Add";
DISPID dispid;
hr=pDispatch->GetIDsOfNames(IID_NULL,
&lpOleStr,
1,
LOCALE_SYSTEM_DEFAULT,
&dispid);//将add映射为dispid
if(FAILED(hr))
{...}
DISPPARAMS dispparms;
memset(&dispparms,0,sizeof(DISPPARAMS));
dispparms.cArgs=2;
VARIANTARG* pArg=new VARIANTARG[dispparms.cArgs];
dispparms.rgvarg=pArg;
memset(&pArg,0,sizeof(VARIANT)*dispparms.cArgs);
dispparms.rgvarg[0].vt=VT_I4;
dispparms.rgvarg[0].lVal=55;
dispparms.rgvarg[1].vt=VT_I4;
dispparms.rgvarg[1].lVal=100;
VARIANTARG varResult;
VariantInit(&varResult);
hr=pDispatch->Invoke(dispid,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&dispparms,
&varResult,
0,NULL);
//备注:
typedef struct tagDISPPARAMS
{
VARIANTARG* rgvarg;
DISPID* rgdispidNamedArgs;
UINT cArgs;
UINT cNameArgs;
}DISPPARAMS;
ID邦定(前邦定)
他提高了性能,并且在编译时进行类型检查
在Visual Basic开发工具中,选择"Visual Basic References"选项添加类型信息
当编译你的工程时,Visual Basic编译器将根据组件中的类型信息检查代码的语法和参数类型,另外,Visual Basic为每个方法
和属性缓存一个DISPID 这就避免了在运行时需检查每一个成员的DISPID
当一个接口改变时,需对组件重新编译
ID邦定例子
Visual Basic
Dim objMath as New Chapter6_Server.Math
Dim nResult as Integer
nResult=objMath.Add(55,100)
C++ID邦定
Class Wizard class..->From TypeLib选项 他将自动化组件产生一个包装类
该包装类提供ID邦定,DISPID的值是在源文件中硬性指定的 支持编译时类型检查
前邦定的需求信息
需要组件提供一定的类型信息,并且要求组件实现一个双向接