Register | Login 
View Article  

Current Articles | Categories | Search | Syndication

Plug-In Architecture With Reflection

By John Spano on Tuesday, February 21, 2006 :: 1014 Views :: 1 Comments :: :: VB.Net

Dot Net has an interesting and very useful concept called Reflection. Since your compiled programs in Dot Net are compiled to IL and not machine code, it is very easy to query an EXE or DLL for what information it exposes in the form of classes, methods and properties, etc. In this article I will show you how to create a very simple and easy method for ”plug-in” type architectures.
 
    Our project will consist of 2 DLL’s and one EXE. Our EXE will show a list box and fill it with any strings of information it finds in compatible classes. When you double click on the box, it will dynamically call the corresponding class that placed the string in the box. Our regular class will have one string and our plug-in class will have another, if the EXE finds the DLL in its directory.
 
    As with all good architectures, we will start with an interface. The interface defined below will be the contract between our main EXE and any plug-in DLL’s that exist. We put the interface in its own DLL so other people can use it. It is typical to have a DLL that is specifically for your interfaces. This allows any other projects to get to them easily. You can also have more control over the distribution of it when others want to add plug-ins to your application. Ours is simple for this demo, but it can be as complex as you need it. Here is its definition:
 
 
Code:
Public Interface IShowInListBox
    Property TextValue() As String
    Sub SayHello()
End Interface
 
 
 
    It has a single property and a sub. The property will return the line of text that we want to show in the list box. The sub will be the code that gets fired when we double click on the item in the list box. Any class that wants to be recognized by our main EXE as a plug-in will have to implement this interface.
 
    We will now look at our two classes that will implement this interface. One is in our main EXE. This one will function as “standard functionality” of our app. The other class is in our second DLL. This one will function as our plug-in class. Here are the definitions.
 
First the standard one:
 
 
Code:
Imports System.Windows.Forms
Public Class MyListItem
    Implements ReflectionInterfaces.IShowInListBox
 
    Sub SayHello() Implements ReflectionInterfaces.IShowInListBox.SayHello
        MessageBox.Show("Hello from My Exe!")
    End Sub
 
    Property IShowInListBox_TextValue() As String _
            Implements ReflectionInterfaces.IShowInListBox.TextValue
        Get
            Return "ListBox Item From Exe"
        End Get
        Set(ByVal Value As String)
        End Set
    End Property
End Class
 
 
 
Now the plug-in class:
 
Code:
Imports System.Windows.Forms
Public Class DllListItem
    Implements ReflectionInterfaces.IShowInListBox
 
    Sub SayHello() Implements ReflectionInterfaces.IShowInListBox.SayHello
        MessageBox.Show("Hello from a DLL Class!")
    End Sub
 
    Property IShowInListBox_TextValue() As String _
            Implements ReflectionInterfaces.IShowInListBox.TextValue
        Get
            Return "ListBox Item From a DLL Class"
        End Get
        Set(ByVal Value As String)
        End Set
    End Property
End Class
 
 
 
    You will notice that they are almost exactly the same. The only difference being their name, what they show in the message box, and the strings they return to show in the list box. Notice also that both of the classes implement ReflectionInterfaces.IshowInListBox. ReflectionInterfaces is the name of the namespace I put our interface in.
 
    Now we will examine the main working code in our EXE. It will load our standard class in the list box and then search for classes in our plug-in DLL that implement our interface and load them also. To show that it picks up only classes that implement IshowInListBox, I created another class that doesn’t implement it and placed it in the DLL also. Its definition is very simple and is as follows:
 
 
Code:
Public Class NonListItem
 
End Class
 
 
 
And now our main EXE:
    
 
Code:
Imports System.Reflection
Imports ReflectionInterfaces
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim myCls As MyListItem = New MyListItem
        lstListBox1.DisplayMember = "TextValue"
        lstListBox1.Items.Add(myCls)
        LoadFromFoundDll()
    End Sub
 
        Private Sub LoadFromFoundDll()
        Dim assemblyObj As Reflection.Assembly = Reflection.Assembly.LoadFrom("C:\VBNet Projects\ReflectionArticle\bin\ReflectionDll.Dll")
        Dim types() As Type
        Dim FoundInterface As Type
        Dim o As Object
        types = assemblyObj.GetTypes
        For Each tp As Type In types
            Try
                FoundInterface = tp.GetInterface("IShowInListBox")
                If Not FoundInterface Is Nothing Then
                    o = assemblyObj.CreateInstance(tp.FullName)
                    Dim oLst As IShowInListBox
                    oLst = DirectCast(o, IShowInListBox)
                    lstListBox1.Items.Add(oLst)
                End If
            Catch
            Finally
                FoundInterface = Nothing
            End Try
        Next
    End Sub
 
    Private Sub lstListBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstListBox1.DoubleClick
        Dim oLst As IShowInListBox
        Dim Lst As ListBox
        Lst = DirectCast(sender, ListBox)
        oLst = DirectCast(Lst.SelectedItem, IShowInListBox)
        oLst.SayHello()
    End Sub
 
 
 
    It’s a single form with a list box on it. I have added a reference to my interface DLL and the corresponding imports for it and also for System.Reflection to get our reflection classes we will use. Now to explain the high points of the code.
 
    If we start in the form load event, you see that I am setting up a new instance of my standard class and adding it to the list box. The key thing to notice here is that I am adding the entire object and not just the text from its property. This is one of Dot Net’s major strong points. I can assign anything to the list box, even whole objects, and pull them out later. I also tell the list box to display the TextValue property of any object that is loaded into it. How do you think it displays text of object that it only knows the name of the property of? If you said reflection you’re right! It uses it internally also to dynamically call the property you specify. After loading the standard class we then call a function that will load our plug-in class.
 
    In our LoadFromFoundDll we hard code the name of the DLL for simplicity. You could change this to search the application’s path for all DLL’s that have classes in them that implement our interface or have it look in the registry for the paths and names of the DLL’s it is supposed to load to make it more useful.
 
    First we want to load our DLL in to memory using the assembly class. After it’s loaded, we can query the DLL for all its classes, which we do by asking for its types and loading them into an array. We then loop through the array and query it to see if it supports our interface. If it does we create an object of the class and load it into our list box.
 
    Now for our last function, the double click event of the list box. In this function, we want to dynamically call the correct object when the user double clicks on it. Since we have the interface as our contract, it is very simple to convert the returned object form the list box into an object of our interface and run the correct subroutine.
 
    As you can see, creating a plug-in architecture in Dot Net is much easier than it used to be in VB6. Reflection allows you to create a robust dynamic application that your end users will appreciate. It can also allow you to control what end functionality the user gets and allow for easier partial patching of your system when you find bugs in specific plug-ins. In a later article we will examine how to read all information from an assembly in Dot Net.
 

Previous Page | Next Page

COMMENTS

Highly appreciated

posted @ Friday, February 16, 2007 3:56 AM by baijnath


Click here to post a comment

Copyright (c) 2008 GSP Developers
Walling Info Systems | Terms Of Use | Privacy Statement