我在VB6中创建了一个DLL文件。它包含一个名为Product
的类,其中包含以下简单代码:
Option Explicit
Private sDescription As String
Public Property Get Description() As String
Description = sDescription
End Property
Public Property Let Description(Value As String)
sDescription = Value
End Property
我想在VB.NET中使用这个DLL,这只不过是在我的系统上注册DLL,并在引用中包含DLL文件。Visual Studio自动生成一个互操作DLL以使用COM DLL。此互操作DLL为所有类生成接口。在VB.NET中,我想创建一个新类,从互操作DLL实现Product
接口。所以我编码:
Imports myAssembly
Public Class NetProduct
Implements myAssembly.Product
Public Property Description As String Implements _Product.Description
Get
Throw New NotImplementedException()
End Get
Set(value As String)
Throw New NotImplementedException()
End Set
End Property
End Class
该属性是自动生成的,因为我实现了Product
接口。但问题来了,因为当我开始使用NetProduct
类时,我会收到一个错误,告诉我:
来自的类型"myProject.NetProduct"中的方法"set_Description"程序集'myProject,版本=1.0.0.0,区域性=中性,PublicKeyToken=null"没有实现。"。
问题是接口中没有方法set_Description
。当我查看Product
接口的定义时,它会显示以下内容:
Imports System.Runtime.InteropServices
Namespace myAssembly
<CoClass(GetType(ProductClass))> <Guid("49CE2F98-931C-441B-B322-9F39B6D6F212")>
Public Interface Product
Implements _Product
End Interface
End Namespace
_Product
接口的定义是:
Imports System.Runtime.InteropServices
Namespace myAssembly
<Guid("49CE2F98-931C-441B-B322-9F39B6D6F212")> <TypeLibTypeAttribute(4304)>
Public Interface _Product <DispId(1745027072)>
Property Description As String
End Interface
End Namespace
当我直接使用接口myAssembly.Product
创建一个新对象时,一切都如您所期望的那样工作。该房产不会在那里造成问题。但是当我在.NET类中实现接口时,问题就出现了。
我该如何解决此问题?
[更新1]创建方法Set_Description后,我看到出现以下错误:
属性"Description"隐式定义了"set_Description"与类"NetProduct"中的同名成员冲突。
这一定与我的问题有关,尽管我不知道它是什么。我已经尝试完成属性以确保Throw New NotImplementedException()
不会妨碍,但这并没有使错误消失。顺便说一下,我的代码构建得很好。我前面给出的错误是运行时错误。不是生成错误。
Private myDescription As String
Public Property Description As String Implements Product.Description
Get
Return myDescription
End Get
Set(value As String)
myDescription = value
End Set
End Property
[更新2]我已经使用JetBrains DotPeek来反汇编Visual Studio生成的interop.dll。反汇编以C#进行编码。它包含2个接口和1个类,用于VB6中的单个Product
类。以下是所有细节。
我将从Product
类本身开始。
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace myAssembly
{
[ClassInterface(0)]
[Guid("C54B96A8-1499-4B76-8508-0B732E551326")]
[TypeLibType(2)]
[ComImport]
public class ProductClass : _Product, Product
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public extern ProductClass();
[DispId(1745027072)]
public virtual extern string Description { [DispId(1745027072), MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [return: MarshalAs(UnmanagedType.BStr)] get; [DispId(1745027072), MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [param: MarshalAs(UnmanagedType.BStr), In, Out] set; }
}
}
ProductClass
使用2个接口。我不明白为什么,因为其中一个只是另一个的实现。这是Product
接口。
using System.Runtime.InteropServices;
namespace myAssembly
{
[CoClass(typeof (ProductClass))]
[Guid("49CE2F98-931C-441B-B322-9F39B6D6F212")]
[ComImport]
public interface Product : _Product
{
}
}
然后我们有了_Product
接口。他们甚至共享相同的Guid。这可能与向后兼容性有关。
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace myAssembly
{
[Guid("49CE2F98-931C-441B-B322-9F39B6D6F212")]
[TypeLibType(4304)]
[ComImport]
public interface _Product
{
[DispId(1745027072)]
string Description { [DispId(1745027072), MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [return: MarshalAs(UnmanagedType.BStr)] get; [DispId(1745027072), MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [param: MarshalAs(UnmanagedType.BStr), In, Out] set; }
}
}
这就是我能找到的全部。仍然不知道Set_Description
的错误来自哪里。
[更新3]示例代码
VB6类的代码位于这个问题的顶部。那里没有什么新奇的东西。在.NET中测试实现的代码如下:
Imports myAssembly
Public Class NetProduct
Implements myAssembly.Product
Private myDescription As String
Public Property Description As String Implements Product.Description
Get
Return myDescription
End Get
Set(value As String)
myDescription = value
End Set
End Property
End Class
为了测试NetProduct
类,我在Form
上放置了一个Button
,并在单击按钮时创建该类的实例。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click '<- Error happens here, so on loading the datatype!
Dim Product As New NetProduct 'Error does NOT happen here.
End Sub
整个项目编译无误。项目运行时甚至没有错误,直到您单击按钮为止。可能是因为NetProduct
类型首先加载在该点上。
我使用了一个控制台应用程序来进行测试。除此之外,我的VB.NET代码与更新3中的代码基本相同。VB.NET属性是VS在使用Implements
语句后使用存根Throw New NotImplementedException()
自动生成的:
Imports OurCOMDll
Class TestClass
Implements OurCOMDll.ClassInCOMDll
Dim msStringProperty As String = String.Empty
Public Property StringProperty As String Implements _ClassInCOMDll.StringProperty
Get
StringProperty= msStringProperty
End Get
Set(value As String)
msStringProperty = value
End Set
End Property
End Class
Module Module1
Sub Main()
Dim o As New OurCOMDll.ClassInCOMDll
o.StringProperty = "Hello World!"
Console.WriteLine(o.StringProperty) ' Outputs 'Hello World!' as expected
Console.ReadLine()
End Sub
End Module
VB6代码也是如此。字符串属性的实现方式与您的类似。迄今为止的区别因素:
- 2019年VS 2017年
- (消费(GUI与控制台应用程序
- 不同的属性名称