如何防止在 ATL 类型库中公开 coclass 实现

Posted

技术标签:

【中文标题】如何防止在 ATL 类型库中公开 coclass 实现【英文标题】:How to prevent coclass implementations from being exposed in an ATL type library 【发布时间】:2010-11-14 12:42:49 【问题描述】:

我正在构建一个具有类工厂类型的 ATL 类型库。有点像这样:

[ object, uuid(...), ... ]
interface INumber : IDispatch 
    [propget, id(0)] HRESULT Value([out, retval] LONG* pVal);


[ object, uuid(...), ... ]
interface INumberFactory : IDispatch 
    [id(1)] HRESULT GetNumber([in] BSTR numberName, [out, retval] INumber* pVal);


[ uuid(...) ]
coclass NumberFactory 
    [default] interface INumberFactory;

然后用户可以通过NumberFactory获得实现INumber接口的类的实例。

这很好用,但我不知道如何定义和实例化通过NumberFactory.GetNumber() 方法返回的 ATL 对象。如果我这样定义 IDL 中的数字:

[ uuid(...) ]
coclass One 
    [default] interface INumber;

One coclass 可以由用户实例化。但我想限制它,所以获得One coclass 实例的唯一方法是调用NumberFactory.GetNumber("One")

所以我的问题是:应该如何编写 IDL,以便用户不能实例化 One,但仍然能够从 NumberFactory coclass 内部实例化 One 并返回 OneINumber 接口给用户?

此外,为了使其正常工作,在 ATL 方面是否必须做一些特别的事情?

【问题讨论】:

【参考方案1】:
    从 IDL 中删除 CoClass 从对象表中删除 CoClass(删除其 OBJECT_ENTRY_AUTO) 保留 CNumber 类 您的 GetNumber(...) 代码应类似于:
*pVal = new CComObject<CNumber>();  
(*pVal)->AddRef();

这样用户就不需要创建 CoClass,而您的工厂是唯一可以生产它们的工厂。

【讨论】:

太棒了!这正是我所需要的!谢谢!这实际上比我发现的更好,哈哈... 您还需要从 CComCoClass 中删除继承。【参考方案2】:

显然我在寻找错误的东西......我在相关问题中找到了答案(来自侧边栏),即使在提问之前我在搜索时无法找到它......

答案有两个:

    noncreatable 添加到 IDL 中的 coclass 定义中 从 ATL 头文件中删除 OBJECT_ENTRY_AUTO 条目(如果由向导生成,则在底部)

请参阅此 MSDN 文章:http://msdn.microsoft.com/en-us/library/4tc639ss.aspx

【讨论】:

实际上,noncreatable 属性是声明 PublicNotCreatable 类的更好方法,因为您可以定义源接口并允许 [VB6] 客户端对 coclass 进行 Dim WithEvents。否则客户端必须直接使用接口。

以上是关于如何防止在 ATL 类型库中公开 coclass 实现的主要内容,如果未能解决你的问题,请参考以下文章

为啥接口上的“添加 IDL 方法”将方法添加到模块以及 CoClass?

ATL ActiveX 控件如何向 javascript 公开布尔值

C# CoClass 属性有啥作用?

C# CoClass 属性有啥作用?

我的$ Foo ATL解决方案中的($ Foo)PS项目是什么?

ATL(COM) 开发下 -- VS2010