65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 VB6 中使用包含列表的 .NET 类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (5投票s)

2009 年 1 月 9 日

CPOL

4分钟阅读

viewsIcon

57197

downloadIcon

2445

创建 VB6 可以使用的 .NET 类包装器很容易,但类型之间存在一些困难,特别是泛型列表。

引言

注意:页面上并非包含所有代码,构造函数和项目下载中提供的其他指令缺失。

本文将在您希望使用在 .NET 中“设计”的类,并通过 Visual Basic .NET 中的“COM 类”在 VB6 中使用的特殊情况下为您提供帮助。

背景

仍有大量公司试图从 VB6 迁移到 .NET。这可能就像运行集成的 VS 转换工具一样简单,或者如果公司有资源和时间,他们会决定重写。

如果这个重写是基于一种新的架构,使用了大多数新应用程序将使用的 N 层和通用 DLL,那很酷... 但是,一旦您完成了其中一个 .NET DLL,您就必须将这个新库集成到您的 VB6 应用程序中,该怎么办?

使用 VB.NET 中的“COM 类”并创建一个调用您组件的业务逻辑层,创建一个 *.tlb 文件并在您的 VB6 项目中引用它,这并不难。然而,有些类型在 VB6 中不可用;例如 .NET 的 Long 在 VB6 中不存在,而 .NET 的 Integer 实际上是 VB6 中的 Long。更不用说 VB6 中根本没有列表(称为泛型),您可以使用数组,但它们在 .NET 中的工作方式与 VB6 不同。

Using the Code

让我们从一个简单的问题开始。

您有以下类

您需要获得一个经销商列表,每个经销商将包含描述和汽车列表,每辆汽车包含制造商、型号、里程和价格。所以您有

public class car
    {
        public string maker { get; set; }
        public string model { get; set; }
        public int mileage { get; set; }
        public int price { get; set; }
    }

public class carDealer
    {
        public string description { get; set; }
        public List<car> carList { get; set; }
    }

public class dealersList
    {
        public List<carDealer> list { get; set; }
    }

您可以从数据库获取数据,我的示例只是硬编码了一些值。

重要的是,最终您将拥有一个 carDealer 类列表作为结果返回。您的主要管理器类看起来大致如下

public class componentManager
    {
        private componentBusinessLogic _bl = new componentBusinessLogic();
        
        //Just a traffic manager
        public dealersList getDealers()
        {
            return _bl.getDealers();
        }
    }

您的 DLL 几乎完成了,您的检索经销商列表的组件。您甚至可以稍微修改一下这个类并接受一个 zipCode 参数并据此检索,但为了方便本文,我们将就这样保留,只检索所有经销商。

现在是时候创建您的 VB6 项目将使用的互操作流量控制器了。您可以使用 Visual Basic .NET 项目中的 COM 类来完成此操作。所以创建一个新的 VB.NET 类库项目。这基本上会为您构建一个即用型接口,您只需创建一个介于您的 C# 类和您的 VB6 项目之间的流量管理器。我们以后称之为 Wrapper Component(包装器组件)。

类似

Public Function GetDealers() As dealerList
        'Just a traffic manager
        Return _bl.getDealers()
 End Function

这里有一个棘手的问题。您可以将您的 carDealer 类声明为 List(of car)对吧?

答案是否定的... VB6 不支持泛型,那么该怎么办?数组?不完全是,它们不像泛型那样是动态的。解决方案:Collection

顺便说一句... 上面代码片段中的 _bl 是我的包装器业务逻辑的一个实例,它包含应用此更改的逻辑,从 <List>CarDealerCollection

因此,您需要稍微更改您的类,并且还需要在它们中包含一些指令,以便 VB6 可以看到它们,例如

Imports System.Runtime.InteropServices

<ClassInterface(ClassInterfaceType.AutoDual)> _
Public Class car

#Region "Fields"
    Private _maker As String
    Private _model As String
    Private _mileage As Integer
    Private _price As Integer
#End Region

#Region "Properties"
    Public Property Maker() As String
        Get
            Return _maker
        End Get
        Set(ByVal value As String)
            _maker = value
        End Set
    End Property

    'Build the rest of the properties here
#End Region
End Class

<ClassInterface(ClassInterfaceType.AutoDual)> _
Public Class carDealer
#Region "Fields"
    Private _description As String
    'IMPORTANT -----------------------------
    'add the word New to this declaration to avoid
    '"Object reference not set to an instance of an object" Error
    Private _carList As New Collection
#End Region

#Region "Properties"
    Public Property Description() As String
        Get
            Return _description
        End Get
        Set(ByVal value As String)
            _description = value
        End Set
    End Property

    Public Property CarList() As Collection
        Get
            Return _carList
        End Get
        Set(ByVal value As Collection)
            _carList = value
        End Set
    End Property
#End Region
End Class

<ClassInterface(ClassInterfaceType.AutoDual)> _
Public Class dealerList
    Private _list As New Collection

    Public Property List() As Collection
        Get
            Return _list
        End Get
        Set(ByVal value As Collection)
            _list = value
        End Set
    End Property
End Class

调用 C# 项目。Component 是 C# 项目的命名空间。

Dim CM As New Component.componentManager
Dim tDealerList As New Component.businessEntities.dealersList
        tDealerList = CM.getDealers()

用您的头脑将 C# 类型转换为您在此项目中声明的 VB 类型,仅此而已,遍历 tDealerList 中的 list 属性,创建一个 VB carDealer 实例,填充它并将其添加到新的 collection 中。最后,这个 collection 将成为您 VB dealierList 中的列表。大致如下

For Each tDealer As Component.businessEntities.carDealer In tDealerList.list
            'Make the new type carDealer from this project
            Dim rCarDealer As New carDealer

            'Get the description from the Component c# project type
            rCarDealer.Description = tDealer.description

            Dim rCars As New Collection
            For Each tCar As Component.businessEntities.car In tDealer.carList
                rCars.Add(New car(tCar.maker, tCar.model, tCar.mileage, tCar.price))
            Next
            
            rCarDealer.CarList = rCars
            rCars = Nothing

            
            rList.List.Add(rCarDealer)
        Next

您完成了。

您可以构建您的应用程序。在命令行中使用以下命令注册您的 DLL 以进行互操作

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm 
	"ComponentWrapper.dll" /tlb /codebase
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\gacutil -i ComponentWrapper.dll

这将创建一个 *.tlb 文件;打开您的 VB6 项目并使您的 tlb 文件具有引用。您将无法引用 DLL,所以不要尝试。

现在在 VB6 中,您基本上可以这样做

Dim list As New ComponentWrapper.dealerList
Dim cManager As New ComponentWrapper.CWManager

Set list = cManager.GetDealers()  

从这里开始... 就看您的了。

关注点

这一切中最酷的地方在于,您现在拥有了一个您的未来 .NET 应用程序可以使用,并且处于过渡期的 VB6 应用程序也可以使用包装器的组件,您只需创建包装器组件即可完成。

我在这段学习过程中遇到的最令人沮丧的部分是泛型无法在 VB6 中使用。最终我发现 VB6 中唯一足够灵活的是 collection。我知道有时使用它可能看起来是一个缺点,但我认为在这种特殊情况下,以及我确定还有许多其他情况,它非常有用。

在将 VB6 应用程序重写为 .NET 时,还有许多其他指南需要遵循,如果您正在创建供 .NET 应用程序和 VB6 应用程序使用的通用 DLL,我发现以下链接对于进行此比较非常有帮助

历史

  • 2009 年 1 月 8 日:初始发布
© . All rights reserved.