在具有不可扩展属性的COM接口上是否允许继承?

时间:2014-07-10 11:44:01

标签: com idl midl

我有一个继承自另一个接口的接口,如下所示:

[
    object,
    uuid(72A6E473-9956-4856-A335-B9169359AACE),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IA : IDispatch
{
    HRESULT MethodA();
}

[
    object,
    uuid(378846D3-7E24-4DAE-B4DF-69AA4B0C1AA9),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IB : IA
{
    HRESULT MethodB();
}

[
    object,
    uuid(4C187526-6809-4A57-A3ED-626E0B36F7DB),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface ICollection : IDispatch
{
    HRESULT GetObject([out, retval] IA** ppValue);
}

ICollection实现将返回一个实现IB的对象。 该对象将通过调度接口提供对MethodA和MethodB的访问。 在运行时不会添加其他成员。

在这种情况下是否允许IA上的不可扩展属性?

1 个答案:

答案 0 :(得分:1)

  

在这种情况下是否允许IA上的不可扩展属性?

是的,是的。

转换为typelib类型标志[nonextensible]的接口的TYPEFLAG_FNONEXTENSIBLE属性具有告诉Visual Basic(6或for Application)不查找具有基础{的缺少成员的实际效果。 {1}}。

IDispatch

如果没有Dim A As IA Set A = Obj ' QueryInterface A.MethodA ' Compilation error ' A.MethodB ' If A.Property Then A.MethodC Dim B As IB Set B = Obj ' QueryInterface B.MethodA B.MethodB ' Compilation error ' If B.Property Then B.MethodC ,Visual Basic会编译缺少的方法调用和属性访问,如果取消注释,则调用[nonextensible]后跟IDispatch::GetIDsOfNames

通常,如果您喜欢编译时检查,这是一件好事,如果需要动态查找,则强制代码将变量声明为IDispatch::InvokeObject。这可能是expando对象的麻烦,但是那些违反了IDispatch's contract的一点:

  

IDispatch :: GetIDsOfNames方法   
...
  的备注   
...
  成员和参数DISPID必须在对象的生命周期内保持不变。这允许客户端获取DISPID一次,并将其缓存以供以后使用。   
...
  警告您无法使用此方法来访问已动态添加的值,例如通过JavaScript添加的值。而是使用IDispatchEx接口的GetDispID。有关更多信息,请参阅IDispatchEx interface。   
...


编辑:以下是您可以尝试使用Word VBA( Alt + F11 )的示例,添加宏并粘贴此文本:

Variant

要试用它,请选择菜单Debug→Compile Project。

它应该成功编译。虽然(默认)接口(for)Dim Docs As Documents Set Docs = Application.Documents Docs.Add ' Compilation error ' Docs.Foo Dim Doc As Document Set Doc = Docs(0) Doc.Activate Doc.Foo 没有Document方法,但它不是Foo(小心双重否定),因此调用转为运行时调度。

现在,取消注释[nonextensible]并重新编译项目。

它应该抛出一个错误,因为(默认)接口(for)Docs.FooDocuments,并且对缺少的[nonextensible]方法的调用不会转变为运行时调度。