泛型和可见的COM .NET库COM、NET

2023-09-06 10:31:22 作者:吃晚安

我已经开发了VB.NET库(C#的部分开发为好),它在很大程度上依赖于从一个抽象的通用基类继承,而我试图找出我们的最佳实践。我可悲的是有它使用的框架3.5的事情。

I've developed a VB.NET library (partially developed on C# as well) that heavily depends on inheriting from an abstract generic base class, and I'm trying to figure out the best practice for this. I Sadly have to do it using framework 3.5.

Public MustInherit Class MyBaseClass(Of T)
  Public Whatever As T
End Class

Public Class MyDerivedClass
  Inherits MyBaseClass(Of String)

  Private _myProperty As String

  Public Property MyProperty As String
    Get
      Return _myProperty
    End Get
    Set(value As String)
      _myProperty = value
    End Set
  End Property
End Class

我附上.tlb文件中VBA(使用Excel)的参考,我运行下面的code:

I attach the .tlb file as a reference in VBA (using Excel), and I run the following code:

Dim m As New VBtoVBA.MyDerivedClass
m.MyProperty = "foo"

和我得到的错误运行时错误430:类不支持自动化或不支持预期的接口。

And I get the error "Run-time error 430: Class does not support Automation or does not support expected interface".

在另一方面,我改第一行:

On the other hand, I change the first lines to:

Public MustInherit Class MyBaseClass
  Public Whatever As String
End Class

Public Class MyDerivedClass
  Inherits MyBaseClass

在VBA脚本的工作。因此,我认为这个问题是仿制药(如记录在其他的来源)。我扔下库的通用功能是不可能的,虽然。 最好的解决办法我能想到的是写第三类,包括MyDerivedClass作为一个字段,可以作为非通用接口它:

The VBA script works. Hence I assume the issue is with generics (as documented in other sources as well). Dropping the generic feature of my library is not possible, though. The "best" workaround I can think of is to write a third class that includes MyDerivedClass as a field, and works as a non-generic interface to it:

Public Class MyDerivedClassString

  Private _innerObj As New MyDerivedClass

  Public Property MyProperty As String
    Get
      Return _innerObj.MyProperty
    End Get
    Set(value As String)
      _innerObj.MyProperty = value
    End Set
  End Property

  Public Property Whatever As String
    Get
      Return _innerObj.Whatever
    End Get
    Set(value As String)
      _innerObj.Whatever = value
    End Set
  End Property

End Class

这样我可以使用它pretty的多,因为我想在VBA:

This way I can work with it pretty much as I'd like to in VBA:

m.Whatever = "wha"
MsgBox (m.Whatever)

通过我认为有可能是另一个(更好)的方式来达到同样的效果的方式,我真的希望如此因为m库是由几十个类别。

By the way I think that there might be another (better) way to achieve the same result, and i really hope so since m library is made up of dozens of classes.

非常感谢。

推荐答案

对于MS Office应用程序是有点...硬codeD。该DLL必须公开的方法和属性可以使用它在COM自动化。为了能够做到这一点,你需要编写接口(S):

As i mentioned in comment writing library (dll) for MS Office applications is bit... hard-coded. This dll must exposes methods and properties to be able to use it in COM automation. To be able to achieve that, you need to write interface(s):

Namespace VBtoVBA
    Public Interface IMyDerivedClass
        Property MyProperty As String
    End Interface
End Namespace

然后DerivedClass

then in DerivedClass

Public Class MyDerivedClass
    Inherits MyBaseClass(Of String)
    Implements IMyDerivedClass

    Private _myProperty As String

    Public Property MyProperty As String Implements IMyDerivedClass.MyProperty

现在,转到项目属性窗口 1)选择应用程序设置页 - 点击大会信息按钮,并在接下来的窗口中选择制作装配COM可见复选框(申请使用确定按钮设定),

Now, go to Project Properties window 1) choose Application tab - click on Assembly Information button and in the next window select Make assembly COM visible checkbox (apply setting using OK button),

2)选择编译选项 - 选择注册COM互操作复选框

2) choose Compile tab - select Register for COM interop checkbox

3)保存项目并生成的dll

3) Save project and Build dll

4)现在,转到Office应用程序的VBA code编辑 - > 引用菜单。在引用窗口添加引用 yourDllName.tlb

4) Now, go to VBA Code editor in Office application -> References menu. In Reference window add reference to yourDllName.tlb

现在,你可以用你的DLL在Office应用程序;)

Now, you can use your dll in Office application ;)

我测试code:

Option Explicit

Sub DoSomething()
Dim m As VBtoVBA.MyDerivedClass

Set m = New VBtoVBA.MyDerivedClass

m.MyProperty = "Something"

MsgBox m.MyProperty


End Sub

和它的工作原理,以及;)

and it works as well ;)