October 9th, 2007
Sooner or later you’ll find that you want to make your application extensible. Perhaps you want to add customer specific processing modules to your backend processes. Maybe you’ll want to offer customers the ability to add their own functionality to your base application. VB.NET and the .NET Framework make this relatively easy to do. Let’s walk through the steps.
Define an Interface
The way to load a .NET assembly dynamically is through reflection. To make this process easier and more controllable within the context of an application I’ve found it best to define a plug-in interface, such as this one:
Public Interface IMyPlugIn Function TestFunction(ByVal value As String) As String Property MySetting() As String End Interface
By using the interface this allows us to have a fixed definition for our plug-ins that our main application to work with. This means that we will need less main app code to support our plug-in.
Create A Class
Now we’re ready to create a plug-in class. Here’s the template that gets created:
Public Class CustomerXYZPlugin Implements MyPlugIn.IMyPlugIn Public Property MySetting() As String Implements MyPlugIn.IMyPlugIn.MySetting Get End Get Set(ByVal value As String) End Set End Property Public Function TestFunction(ByVal value As String) As String Implements MyPlugIn.IMyPlugIn.TestFunction End Function End Class
Now, to complete the plug-in class we will need to add appropriate code it. You can’t define constructors in an interface so you’ll find it best to specify that you’ll either use a parameterless constructor or require that plug-in classes support a specific set of parameters. My preference has been to use parameterless ones and to supply ample properties for the plug-ins.
As for other code, as long as you define the interface you can do just about anything else you want.
Loading The Plug-In
Now we get to the heart of the matter, how to load the plug-in. There are several approaches you can take to this but here’s mine. First, let’s look at the code:
Private Function LoadPlugIn(ByVal LoadPath As String) As MyPlugIn.IMyPlugIn Dim NewPlugIn As MyPlugIn.IMyPlugIn Try Dim PlugInAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom(LoadPath) Dim Types() As Type Dim FoundInterface As Type Types = PlugInAssembly.GetTypes For Each PlugInType As Type In Types FoundInterface = PlugInType.GetInterface("MyPlugIn.IMyPlugIn") If FoundInterface IsNot Nothing Then NewPlugIn = DirectCast(PlugInAssembly.CreateInstance(PlugInType.FullName), MyPlugIn.IMyPlugIn) Exit For End If Next Catch ex As Exception 'handle exceptions here End Try Return NewPlugIn End Function
As you can see, we’re passing in the path to our plug-in and returning a plug-in interface object from the call. After declaring our return value we enter a try block. I recommend putting this loader logic in an exception handling block since you may be dealing with code that’s outside your direct control.
Next, we create a new Reflection.Assembly object from the file location that was passed into our function and extract the types from it. This allows a plug-in to have functionality beyond just the interface. We search for our interface and, when we find it, create a new instance and exit our search loop. Then we pass back the newly created plug-in object back to our main code.
Here’s a simple example of what the main code might look like:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click Dim NewPlugIn As MyPlugIn.IMyPlugIn = LoadPlugIn(TextBox1.Text) NewPlugIn.MySetting = "Hello World" Dim OurTestPlugInValue As String = NewPlugIn.TestFunction("Try It!") End Sub
Those are the steps to adding a simple plug-in to your application. Of course, there are more things you can do with Reflection and I suggest that you investigate them if you’re thinking about implementing this in one of your apps. Remember that there is a performance penalty for using Reflection and there are security considerations as well so make sure you factor them into your design.
If you have any questions or observations about using Reflection to create plug-ins, let me know by leaving a comment.
Rate This Article: