Naigewron
Member
Hi!
I am currently developing an application that will be the "base" for several components (business reporting systems, order management, etc). The idea is that our customers will install this "mother application", and we will offer components that will slot into it, expanding the functionality.
Now, here's my idea for how to make this work. I have some of this basic functionality down, but I want to get other people's opinions, ideas and experiences with this sort of thing before I move too far in a direction that might not be the best way to go:
- The components have an "interface" that is inherited from a base class that both the mother application and the component knows about. This will be their means of communicating with eachother
- The components are compiled into DLLs. The mother application goes through these DLLs and looks for an implementation of the base interface:
Here is the "complete" Sub for loading the components
The important bit is really this, which deals with the creating and loading of a named assembly:
ModuleCollection is simply a class that extends CollectionBase:
(I'm aware that referring to the components as "Modules" might make the code a bit hard to read, and I've since realised the error of my ways. This will be rewritten )
Hopefully this post makes some sense. Basically, The mother application needs to dynamically load "add-on" components that are not compiled into or together with the actual application (ie: The mother application has absolutely zero knowledge about the component at compile-time). We need to be able to add a DLL to the application at any time, and have the mother application be able to use it to load MDI child forms, menus, toolstrips and generally use it to expand its own functionality. Am I on the right path here, or is there some other way I should look at?
I am currently developing an application that will be the "base" for several components (business reporting systems, order management, etc). The idea is that our customers will install this "mother application", and we will offer components that will slot into it, expanding the functionality.
Now, here's my idea for how to make this work. I have some of this basic functionality down, but I want to get other people's opinions, ideas and experiences with this sort of thing before I move too far in a direction that might not be the best way to go:
- The components have an "interface" that is inherited from a base class that both the mother application and the component knows about. This will be their means of communicating with eachother
- The components are compiled into DLLs. The mother application goes through these DLLs and looks for an implementation of the base interface:
Here is the "complete" Sub for loading the components
VB.NET:
Public LoadedModules As New ModuleCollection
Private Sub LoadModules()
Try
' Information installed modules is stored in a database table.
' Retrieve it and go through the data rows to load each module
Dim dtModules As New SystemDataset.BUS_InstalledModulesDataTable
g_taInstalledModules.Fill(dtModules)
' Clear the module collection
LoadedModules.Clear()
For Each rw As SystemDataset.BUS_InstalledModulesRow In dtModules.Rows
' The module directory name.
' MODULES_FOLDER is just a string constant containing the
' application path subfolder name where the modules reside
Dim dirInfo As New System.IO.DirectoryInfo(Application.StartupPath & "\" & MODULES_FOLDER & "\" & rw.ModuleFolder)
Try
' Just check some folder rights and stuff
If CheckFolderRights(dirInfo.FullName) <> FolderRight.Full Then
Throw New Exception("Insufficient access to module folder '" & _
rw.ModuleFolder & "' (need full read/write access)! " & _
"Aborting module load for module '" & rw.Name & "'.")
End If
' Create an assembly object and try to load the
' assembly name from the datarow (e.g. "ComponentName")
Dim asm As Reflection.Assembly
asm = Reflection.Assembly.LoadFrom(dirInfo.FullName & "\" & rw.ModuleAssembly)
' Try to create an instance of the common interface,
' so that the mother application will have an object to
' communicate with the component through
Dim mdl As BaseModule
mdl = asm.CreateInstance(rw.ModuleNamespace & "." & rw.ModuleInterface)
mdl.ModuleId = rw.Module_ID
' Add the newly loaded component to the collection
LoadedModules.Add(mdl)
Catch ex As Exception
ExceptionHandler(ex)
End Try
Next
Catch ex As Exception
ExceptionHandler(ex)
End Try
End Sub
The important bit is really this, which deals with the creating and loading of a named assembly:
VB.NET:
' Create an assembly object and try to load the
' assembly name from the datarow (e.g. "ComponentName")
Dim asm As Reflection.Assembly
asm = Reflection.Assembly.LoadFrom(dirInfo.FullName & "\" & rw.ModuleAssembly)
' Try to create an instance of the common interface,
' so that the mother application will have an object to
' communicate with the component through
Dim mdl As BaseModule
mdl = asm.CreateInstance(rw.ModuleNamespace & "." & rw.ModuleInterface)
mdl.ModuleId = rw.Module_ID
ModuleCollection is simply a class that extends CollectionBase:
VB.NET:
Public Class ModuleCollection
Inherits System.Collections.CollectionBase
Public Sub Add(ByVal Mdl As BaseModule)
' Invokes Add method of the List object to add a widget.
List.Add(Mdl)
End Sub
Public Sub Remove(ByVal index As Integer)
If index > Count - 1 Or index < 0 Then
Throw New Exception("Error removing item! No module at index " & index & "!")
Else
List.RemoveAt(index)
End If
End Sub
Public ReadOnly Property Item(ByVal index As Integer) As BaseModule
Get
Return CType(List.Item(index), BaseModule)
End Get
End Property
End Class
(I'm aware that referring to the components as "Modules" might make the code a bit hard to read, and I've since realised the error of my ways. This will be rewritten )
Hopefully this post makes some sense. Basically, The mother application needs to dynamically load "add-on" components that are not compiled into or together with the actual application (ie: The mother application has absolutely zero knowledge about the component at compile-time). We need to be able to add a DLL to the application at any time, and have the mother application be able to use it to load MDI child forms, menus, toolstrips and generally use it to expand its own functionality. Am I on the right path here, or is there some other way I should look at?
Last edited: