我正在构建一个将用于VBA项目的VB.NET类库。在我的图书馆里,我有一个名为" Globals"我希望在:
中存储一些全局(库级)属性和方法Imports System.Runtime.InteropServices
<ComVisible(True)>
Public Module Globals
<ComVisible(True)>
Public Const TestGlobal As Integer = 0
End Module
但是,当我在Excel VBE中引用我的库时,我的模块显示为一个类,我无法在对象浏览器中看到我的常量变量:
我错过了什么或做错了导致我的模块出现在课堂上?
答案 0 :(得分:2)
有些阻抗不匹配&#34; VB.NET和COM之间。 COM主要用于接口,.NET以一种使COM更容易访问的方式从VB项目构建.tlb文件。 VB.NET中的Module
基本上只是托管世界中的静态类。当从代码构建interop程序集时,它会看到一个类,将它包装在一个接口中,并将接口附加到该类:
请注意,无法为Module
提供自己的接口实现,因为.NET中的静态类无法实现接口。
您在.NET中无法做的另一件事是创建不包含在类中的成员过程。这基本上是COM世界中的Module
。例如,看一下VBA Strings模块的IDL:
module Strings { [entry(516), helpcontext(0x000f665f)] short _stdcall Asc([in] BSTR String); [entry(537), helpcontext(0x000f6e9f)] BSTR _stdcall _B_str_Chr([in] long CharCode); [entry(608), helpcontext(0x000f64e2)] VARIANT _stdcall _B_var_Chr([in] long CharCode); [entry(517), helpcontext(0x000f6ea0)]
请注意,所有条目都指定了.dll入口点。这主要是因为你正在进行你在C世界中发现的各种各样的原始函数调用。如果.NET世界中存在模拟,那么在 命名空间 级别而不是类(或者类别)声明Sub
或Function
模块)级别......
<ComVisible(True)>
Namespace SomeClass.Functions
<ComVisible(True)>
Public Function Foo() As String
Return "Foo"
End Function
End Namespace
......这显然不是有效的.NET代码。
在相关说明中,请记住,您无法在VBA 中看到整个图片。 VBA基本上是建立在COM之上,但它很难抽象出大部分内容。 VBA模块可以将所有意图和目的视为静态类。例如,您可以为它们提供属性,公共成员等。在一天结束时,VBA对象浏览器是否将某些内容视为类,模块或其他内容并不重要 - 重要的是您可以使用非托管上下文中的托管代码。只需解决两个基础设施中的差异,以获得可用的东西并称之为一天:
Imports System.Runtime.InteropServices
<ComVisible(True)>
Public Enum Constants
GlobalOne = 0
GlobalTwo = 1
GlobalEtc = 2
End Enum
<ComVisible(True)>
Public Class FunctionProvider
<ComVisible(True)>
Public Function Foo() As String
'Note that the class doesn't need to keep track of "state" to be usable.
Return "Foo"
End Function
End Class