服务器端编程之如何开发IDispatch接口的实现类

来源:互联网 发布:桥接模式java类图 编辑:程序博客网 时间:2024/06/07 13:09

首先需要决定的是是否使用type infomation?

那些简化IDispatch实现的helper method需要使用类型信息。

IDispatch接口的四个方法从客户端的角度来看是关联的。

      1. IDispatch::GetTypeInfoCount

            IDispatch::GetTypeInfoCount function is called by the client to determine whether type information is available for the object.

            如果有类型信息,则实现类在初始化时需要获取IDispatch子接口的类型信息以便后续方法使用。

     2. IDispatch::GetTypeInfo

         获取IDispatch子接口的类型信息。

     3. IDispatch::GetIDsOfNames

         实现IDispatch的子接口可能有多个方法,此方法即根据输入的method name及其参数名得到DISPID以便调用Invoke方法。

      4. IDispatch::Invoke

         第一个参数就是上面得到的DISPID,代表要调用哪个方法。第五个参数是一个DISPPARAMS结构体数组,包含相应的参数信息。

如果client端通过调用GetIDsOfNames获取dispid然后再调用invoke则称为late binding。如果通过type library获取dispid缓存以便使用则成为early binding。

由于IDispatch自动化接口不容易使用,微软推荐采用dual interface, 即面向不同的客户端,如果client采用VB Script则通过自动化接口访问,如果client端采用C++则使用custom interface即COM技术。

DISPPARAMS:   

typedef struct tagDISPPARAMS {    // Array of arguments    [size_is(cArgs)] VARIANTARG* rgvarg;    // Array of DISPIDs of named arguments    [size_is(cNamedArgs)] DISPID* rgdispidNamedArgs;    // Total number of arguments    UINT cArgs;    // Number of named arguments    UINT cNamedArgs;} DISPPARAMS;

理解position arguments VS named arguments

首先理解

1) Parameters are automatically assigned a DISPID value based on their position within the argument list. For example, theSum method has three parameters that are implicitly assigned DISPIDs as follows:

HRESULT Sum([optional, defaultvalue(-1)] int x, // DISPID = 0            [optional, defaultvalue(-1)] int y, // DISPID = 1            [out, retval] int* retvalue);       // DISPID = 2

2) 参数数组rgvarg是按照相反的顺序来存储参数的。so that rgvarg[0] contains the last argument andrgvarg[cArgs _ 1] contains the first argument。

以named arguments为例来说明DISPPARAMS的设置。

To omit an optional parameter when you use named arguments, you just don't pass it.

VARIANTARG SumArg;VariantInit(&SumArg);SumArg.vt = VT_I4;SumArg.lVal = 5;
//用DispId=1来表明上面设置的参数5是针对y的。
DISPID DispId = 1; // The y parameterDISPPARAMS Params = { &SumArg, &DispId, 1, 1 };// Now IDispatch::Invoke calls ISum::Sum(-1, 5)

Building Automation Clients in C++

     1. Initializing COM (CoInitializeEx)

     2. Instantiating a class (CoCreateInstance)

     3. 调用QueryInterface获取IDispatch的实现类

     4. 如果第三步成功则调用IDispatch::GetIDsOfNames获取DISPID

     5. 调用invoke

         此方法最困难的部分就是准备包含方法参数的DISPPARAMS结构体。

         这里需要注意的是参数是按照从右到左的顺序存储在dispparams结构体中的数组中的。

        namedarguments & positionarguments两种方式构建DISPPARAMS。

原创粉丝点击