Да, вы можете создать архитектуру надстройки. Вы должны создать как минимум три сборки, то есть проекты в Visual Studio. Конечно, вам нужно основное приложение winforms в виде исполняемого файла.
Тогда вам нужна библиотека классов, объявляющая интерфейсы. Эти интерфейсы должны определять, что может делать надстройка. Я могу только дать вам очень грубое впечатление, поскольку конкретные детали сильно зависят от того, что должны делать надстройки. Вы можете иметь очень простое определение надстройки, которое выглядит так:
Public Interface IAddIn
ReadOnly Property Name As String
ReadOnly Property Version As String
End Interface
Конечно, такая надстройка не может многое сделать, но она позволяет исполняемому файлу идентифицировать класс как надстройку и перечислить его имя в версии в диалоговом окне about. Вы можете добавить дополнительные функции непосредственно к этому интерфейсу или создать разные интерфейсы для разных типов надстроек. Например. Если надстройка хочет добавить свои собственные пункты меню в существующее меню, вы можете позволить ей реализовать этот интерфейс (в дополнение к 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