C# 如何将结构或类从.NET COM dll返回到使用VB6的应用程序?
这似乎很容易在这里找到,但如果以前有人问过,我不知道在哪里 基本上,我是一名.NET开发人员,必须使用VB6一分钟,学习如何制作COM DLL。我正在使用C#并试图获得一个用该语言制作的COM DLL,以将自定义类/结构返回到某些VB6代码中,虽然在从COM方法返回C# 如何将结构或类从.NET COM dll返回到使用VB6的应用程序?,c#,.net,dll,com,vb6,C#,.net,Dll,Com,Vb6,这似乎很容易在这里找到,但如果以前有人问过,我不知道在哪里 基本上,我是一名.NET开发人员,必须使用VB6一分钟,学习如何制作COM DLL。我正在使用C#并试图获得一个用该语言制作的COM DLL,以将自定义类/结构返回到某些VB6代码中,虽然在从COM方法返回字符串或int时,答案很容易使用,但我很难让它与实际对象一起工作 示例代码: C# 当返回值是string或int(并且result声明为string)时,这种方法非常有效,此时可以将值传递到MsgBox,并向用户显示。但是如果返回了
字符串
或int
时,答案很容易使用,但我很难让它与实际对象一起工作
示例代码:
C#
当返回值是string
或int
(并且result
声明为string
)时,这种方法非常有效,此时可以将值传递到MsgBox
,并向用户显示。但是如果返回了
或Test
,任何通过结果的尝试。[toString()/Test1/Test2]
到MsgBox
都会导致消息“start”和“end”仍然很好地显示给用户,但在这两者之间没有任何显示(甚至没有空白消息)
值得注意的是,通过返回Test
的实例并将result
声明为String
,对MsgBox(result)
的调用将显示“One.Two.Three.Test”,这表明那里发生了一些事情
所以…问题是:
要使VB6应用程序能够公平地访问此对象,还需要执行哪些操作
特别是,我需要返回一个数组、List
,或者一些每个对象都有几个成员的对象。同样,这似乎应该在谷歌上比较容易找到,但它似乎被其他搜索结果掩盖了
另外,dll的.NET框架是4.5。(我在4.0文件夹中使用了RegAsm,而不是链接答案中特别提到的2.0)。如果需要将其降低到4.0,我可能可以,但不可能将其一直降低到2.0。实现这一点的方法不止一种,这里有一个简单的方法与您的工作方式相匹配: C#代码可能非常简单,您不需要明确地声明接口,不需要到处使用
ref
关键字等,但您确实需要为类添加ComVisible(true)
属性(string、int等隐式ComVisible):
VB/VBA代码:
Dim result As Object
Dim someObj
Set someObj = CreateObject("One.Two.Three.SomeClass")
' note the "Set" keyword, it's mandatory for COM objects...
Set result = CallByName(someObj, "SomeFunction", VbMethod, "hello world")
MsgBox result.Text
但是,如果您想从VB/VBA获取Intellisense,也可以这样声明类:
// progid is now optional because we won't need CreateObject anymore
[ProgId("One.Two.Three.SomeClass")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeClass1
{
public SomeClass2 SomeFunction(string text)
{
return new SomeClass2 { Text = text };
}
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeClass2
{
public string Text { get; set; }
}
我刚刚添加了ClassInterfaceType.AutoDual
,现在我可以引用一个TLB(我使用regasm/TLB创建的),并在VB/VBA中使用此代码:
Dim c1 As New SomeClass1
Set c2 = c1.SomeFunction("hello world")
MsgBox c2.Text
ClassInterfaceType.AutoDual
不被“推荐”,因为如果你这样做,你必须确保COM客户端(这里是VB/VBA)和COM服务器(这里是C#)之间的二进制文件100%同步,否则你可能会遭受严重的VB/VBA崩溃。然而,这是一个折衷方案,intellisense是一个伟大的生产力工具
最后一句话是返回
列表
,你会有麻烦的。如果你面对它,问另一个问题:-)谢谢!在我的例子中,通过调用CallByName
添加Set
关键字似乎是最重要的事情。
Dim result As Object
Dim someObj
Set someObj = CreateObject("One.Two.Three.SomeClass")
' note the "Set" keyword, it's mandatory for COM objects...
Set result = CallByName(someObj, "SomeFunction", VbMethod, "hello world")
MsgBox result.Text
// progid is now optional because we won't need CreateObject anymore
[ProgId("One.Two.Three.SomeClass")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeClass1
{
public SomeClass2 SomeFunction(string text)
{
return new SomeClass2 { Text = text };
}
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeClass2
{
public string Text { get; set; }
}
Dim c1 As New SomeClass1
Set c2 = c1.SomeFunction("hello world")
MsgBox c2.Text