首页 > 解决方案 > 补丁支持多个版本的应用程序

问题描述

我编写了一个 vb.net Windows 窗体应用程序,基本上,它允许用户将来自多个源的数据加载到网格上,对行和列执行数学和逻辑运算,然后导出结果。

一些用户要求只有他们需要的功能,我很乐意提供。但是,这会导致应用程序的多个版本和各种维护问题。

我想通过制作应用程序的标准版本来解决这个问题,能够向要求自定义功能的用户发送某种补丁来升级他们的版本。我的第一个想法是将需要动态的代码部分放入 .dll 中,并提供某种接口来从应用程序本身更改 dll 版本。那可能吗?或者我应该求助于一些安装软件来完成这个?

我不是在这里寻找食谱,只是朝着正确的方向轻推让我开始。欢迎任何建议或警告!

标签: vb.netdynamicdll

解决方案


是的,您可以创建插件架构。您必须至少创建三个程序集,即 Visual Studio 中的项目。当然,您需要将主要的 winforms 应用程序作为可执行文件。

然后你需要一个声明接口的类库。这些接口必须定义插件可以做什么。我只能给你一个非常粗略的印象,因为具体细节很大程度上取决于加载项必须做什么。您可以有一个非常基本的插件定义,如下所示:

Public Interface IAddIn
    ReadOnly Property Name As String
    ReadOnly Property Version As String
End Interface

当然,这样的插件不能做很多事情,但它允许可执行文件将一个类识别为插件,并在 about-dialog 中列出其名称和版本。您可以直接向此界面添加附加功能,也可以为不同类型的加载项创建不同的界面。例如,如果一个插件想要将它自己的菜单项添加到现有菜单中,您可以让它实现这个接口(除了IAddIn):

Public Interface IMenuItemProvider
    ReadOnly Property MenuItems As IEnumerable(Of ToolStripMenuItem)
End Interface

你可以定义数学函数或任何你需要的东西。

然后,您可以使用加载项类创建类库项目。主可执行文件和加载项都必须使用接口引用项目。这会在可执行文件和加载项之间创建一个绑定。

可执行文件需要一些代码来加载加载项。我已将此代码放入一个类中。(我已经将它从 C# 翻译成 VB 没有测试):

Public Class AddInLoader
    Public Function Load(ByVal folder As String) As IList(Of IAddIn)
        Dim addIns = New List(Of IAddIn)()
        Dim files As String() = Directory.GetFiles(folder, "*.dll")

        For Each file As String In files
            addIns.AddRange(LoadFromAssembly(file))
        Next

        Return addIns
    End Function

    Private Shared Iterator Function LoadFromAssembly(ByVal fileName As String) As IEnumerable(Of IAddIn)
        Dim asm As Assembly = Assembly.LoadFrom(fileName)
        Dim addInInterfaceName As String = GetType(IAddIn).FullName

        For Each type As Type In asm.GetExportedTypes()
            Dim interfaceType As Type = type.GetInterface(addInInterfaceName)

            If interfaceType IsNot Nothing AndAlso (type.Attributes And TypeAttributes.Abstract) <> TypeAttributes.Abstract Then
                Dim addIn As IAddIn = CType(Activator.CreateInstance(type), IAddIn)
                Yield addIn
            End If
        Next
    End Function
End Class

使用此类,您可以像这样加载加载项

Dim loader = New AddInLoader()
Dim addIns As IList(Of IAddIn) = loader.Load(myAddInFolder)

For Each addIn As IAddIn In addIns
    Dim menuProvider = TryCast(addIn, IMenuItemProvider)

    If menuProvider IsNot Nothing Then
        For Each menuItem As ToolStripMenuItem In menuProvider.MenuItems
            //TODO: Add menu item to application menu
        Next
    End If
Next

推荐阅读