Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将结构或类从.NET COM dll返回到使用VB6的应用程序?_C#_.net_Dll_Com_Vb6 - Fatal编程技术网

C# 如何将结构或类从.NET COM dll返回到使用VB6的应用程序?

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,并向用户显示。但是如果返回了

这似乎很容易在这里找到,但如果以前有人问过,我不知道在哪里

基本上,我是一名.NET开发人员,必须使用VB6一分钟,学习如何制作COM DLL。我正在使用C#并试图获得一个用该语言制作的COM DLL,以将自定义类/结构返回到某些VB6代码中,虽然在从COM方法返回
字符串
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