VB.NET - 模块在VBE中被解释为类

时间:2017-02-23 00:49:35

标签: vb.net vba dll

我正在构建一个将用于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中引用我的库时,我的模块显示为一个类,我无法在对象浏览器中看到我的常量变量:

VBE Object Browser

我错过了什么或做错了导致我的模块出现在课堂上?

1 个答案:

答案 0 :(得分:2)

有些阻抗不匹配&#34; VB.NET和COM之间。 COM主要用于接口,.NET以一种使COM更容易访问的方式从VB项目构建.tlb文件。 VB.NET中的Module基本上只是托管世界中的静态类。当从代码构建interop程序集时,它会看到一个类,将它包装在一个接口中,并将接口附加到该类:

OP's code in ITypeLib Viewer

请注意,无法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世界中存在模拟,那么在 命名空间 级别而不是类(或者类别)声明SubFunction模块)级别......

<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