我想构建一个 COM可见 C#类,比如DynamicComponent
,它将通过COM提供动态界面。
在这个类中,这个类将维护一个代表字典:
"GetTheAnswer" -> () => { return 42; }
"Add" -> (int a, int b) => { return a + b; }
...
客户端代码将是一些VBA。
这是我天真想象的工作流程:
DynamicComponent
(至少得到Excel / VBA提供的存根)["GetTheAnswer" -> 1, "Add" -> 2]
GetTheAnswer
和Add
我的第一个问题:是否可能?
如果不是:为什么?
如果是:如何?
根据我对COM的了解,如果可能, IDispatch COM界面是我最好的朋友。
此外,根据我的理解,.Net 4的 ICustomQueryInterface 界面也可以提供很大帮助。
但是现在COM并不是真正的尖端;)很难找到像代码样本这样的资源。
我找到了这个有趣的示例:https://clrinterop.codeplex.com/releases/view/32350使用 ICustomQueryInterface 接口实现COM聚合
但它不是动态的,而是基于静态定义的类型和接口。
非常感谢任何帮助。
感谢。
答案 0 :(得分:5)
公开IDispatchEx
适用于JavaScript,但我认为VBA不会使用它。 AFAIK,VBA依赖IDispatch
进行后期绑定。此外,C#dynamic
非常适合在.NET端使用基于COM IDispatch
的对象,但反之亦然。出于某种原因(.NET设计师决定?),ExpandoObject
和DynamicObject
的动态属性和方法默认情况下不会暴露给COM。
幸运的是,有一种方法可以覆盖它:通过实现IReflect接口。有关实施细节,请参阅此优秀blog post。我自己看了at exposing properties of C# anonymous class to COM,最后使用了IReflect
。这是您向COM公开动态方法和属性的方法。形象地说,IReflect
作为IDispatch
向COM公开。
另外,IExpando为IDispatchEx
执行相同的工作,因此JavaScript客户端可以添加以后可以通过托管代码访问的新属性。
[更新] 下面是一个原型实现,它将DynamicComponent
的实例公开给在WebBrowser
内运行的VBScript。它适用于VBScript,也应该适用于VBA。虽然,我怀疑VBA自动完成是否有效,或者有一种简单的方法来实现这样的功能。 AFAIU,VBA自动完成依赖于COM类型库(可通过IDispatch::GetTypeInfo
获得),但我不认为.NET互操作引擎在通过{{1}实现IDispatch
时会生成动态类型库} (我可能错了)。此外,此实现对于逐个名称的查找区分大小写,应该调整,因为VB不区分大小写。
IReflect
答案 1 :(得分:0)
您无法动态创建接口,但您可以创建方法。在C#中查看Expando Objects。
特别是,您可以使用expandos创建自定义IDispatchEx实现;您可以使用expando将名称映射到ID,使用反射来调用对象。