Click here to Skip to main content
15,891,372 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a project where I am sending commands to a camera to control it's menu's. I have created 2 dll's. 1 for brand A and the other for brand B and will require others.

I want to sell the dll's as options to add capability to the software, where on load, it scans for the existance of these dll's and adds them to a combobox.

In my code, I can create a reference to a dll and in design time refer to it as follows and all works but I cannot work out how I can fill a combo box (secondary issue) and allow the user to select from a dropdown box the other protocol and load it's dll (primary issue).

Dim mProtocol As New CameraAProtocol.Protocol
Dll code:
VB
Public Class Protocol

    Private Shared sMessage As String = ""
    Private Const mSTX As String = Chr(2)
    Private Const mETX As String = Chr(3)

    Public Class MenuOn
        Public Shared ReadOnly Property Command()
            Get
                sMessage = mSTX & "menuon" & mETX
                Return sMessage
            End Get
        End Property

        Public Shared ReadOnly Property Message()
            Get
                sMessage = ""
                Return sMessage
            End Get
        End Property
    End Class

    Public Class MenuOff
        Public Shared ReadOnly Property Command()
            Get
                sMessage = mSTX & "Menu Off" & mETX
                Return sMessage
            End Get
        End Property

        Public Shared ReadOnly Property Message()
            Get
                sMessage = ""
                Return sMessage
            End Get
        End Property
    End Class
End Class
Posted
Updated 6-Jul-10 4:34am
v3

For your primary issue, what you're looking for is the Assembly.LoadFrom method. Presumably, they will all have the same methods within them. I would create an interface class and have all of your other classes implement that interface. Then, you can write your methods based on the interface. Then, you just create the actual instance of the object when they choose which camera they're using.

Presumably, the interface would have a property called CameraBrand or something similar. To get the list of dll's, you can either store them in the registry which would allow for different file paths, or you can force them to be stored in a specific location. But, either way, you look for the different dll's, then use the interface class to pull out the camera brand and fill your combobox that way.

I've never had the need to do anything like that, but that's what I would start with. I can't guarantee that would work, but again, that's where I would start.
 
Share this answer
 
Comments
Tim Norton 7-Jul-10 8:14am    
Thanks for this suggestion. Part of it helped, combined with another reference, which I can not find to link to.
I cna now load 2 or more dll's dynamically
<pre lang="vb">Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
       Dim StrAssembly As String = "CustomPlugin1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ef086aa3bcfa80b5"
       Plugin = System.Reflection.Assembly.Load(StrAssembly)
       Dim Instance As StandardPlugin.Cls_Main
       Instance = DirectCast(Plugin.CreateInstance("CustomPlugin1.Cls_Main"), StandardPlugin.Cls_Main)

       Instance.DoTest()
   End Sub




I am not having luck with the Interface as you cannot seem to use it for nested classes.
I also tried using a MustInherit class and mustoverride property but again became stuck with the nested classes.
So, here is what I have done...(This is going to be a long answer)

I created one solution in VS just to make the dlls. In that solution, I started with an Interface. It looks like:
VB
Public Interface CameraInterface
    ReadOnly Property Brand As String
    ReadOnly Property Version As String
    ReadOnly Property Model As String
    Function FullInformation() As String
End Interface

Then, I created 3 other projects within that solution...one for a different type of camera. In those projects, I added the reference to the InterfaceClass (the namespace for CameraInterface). Then, in the class, I implemented the interface. It looks like:
VB
Public Class CanonPowershot
    Implements InterfaceClass.CameraInterface


    Private Const _brand As String = "Canon"
    Public ReadOnly Property Brand As String _
      Implements InterfaceClass.CameraInterface.Brand
        Get
            Return _brand
        End Get
    End Property

    Public Function FullInformation() As String _
      Implements InterfaceClass.CameraInterface.FullInformation
        Return _brand & " " & _model & ", v." & _version
    End Function

    Private Const _model As String = "Powershot"
    Public ReadOnly Property Model As String _
      Implements InterfaceClass.CameraInterface.Model
        Get
            Return _model
        End Get
    End Property

    Private Const _version As String = "1.23"
    Public ReadOnly Property Version As String _
      Implements InterfaceClass.CameraInterface.Version
        Get
            Return _version
        End Get
    End Property
End Class


Once I had created these classes, I build the dll's.

From there, I created a new solution for testing the interface. Once again, I added a reference to the InterfaceClass. I created a simple form with a menu. The first menu item was my LoadFiles ToolStripMenuItem. I created a simple form to allow the user to select the files to load and then copied them to a directory that I set up.

The other menu item simply lists the different dll's that have been loaded. To load the dll's, I first look for the directory, then get the files in the directory and look for the dlls. I have an array of assemblies that I use to store each camera type. As I add a new dll, I increment the array and create a new array from the file. Then, I have to see if there is a type within that array that I can use the interface for. To do that, I cycle through the types in the assembly and check if it has the interface that we need. If it does, I create a new instance of the type and create a new menu item. The LoadDlls method looks like:

VB
Private Sub LoadDlls()
    If Not Directory.Exists("D:\Temp\Dlls") Then
        CamerasToolStripMenuItem.Enabled = False
    Else
        Dim enableCamera As Boolean = False
        ReDim myAssembly(-1)

        For Each st As String In Directory.GetFiles("D:\Temp\Dlls")
            If Path.GetExtension(st) = ".dll" Then
                enableCamera = True
                ReDim Preserve myAssembly(UBound(myAssembly) + 1)
                myAssembly(UBound(myAssembly)) = Assembly.LoadFrom(st)
                'see if we can create an interface class from it
                Dim testInterface As CameraInterface
                Dim currentAssembly As Integer = UBound(myAssembly)
                With myAssembly(currentAssembly)
                    For i = 0 To .GetTypes.Count - 1
                        Try
                            If (.GetTypes()(i).GetInterface("CameraInterface")) IsNot Nothing Then
                                testInterface = TryCast(.CreateInstance(.GetTypes()(i).FullName), CameraInterface)
                            End If
                        Catch ex As Exception
                            testInterface = Nothing
                        End Try

                        If testInterface IsNot Nothing Then
                            Dim newItem As New ToolStripMenuItem(testInterface.Brand & " " & testInterface.Model)
                            CamerasToolStripMenuItem.DropDownItems.Add(newItem)
                            Exit For
                        End If
                    Next
                End With
            End If
        Next
        CamerasToolStripMenuItem.Enabled = enableCamera
    End If
End Sub


You would have to keep track of which type came from which assembly and which type within that assembly, but you could create a simple struct with that information and add that struct to the menu item's tag property. Then, you could easily get to the right assembly and the right type any time you needed to use it.

As far as nested classes, I'm not sure about that or exactly what you're doing. I believe that you can have as many nested classes within an interface as you want. But you wouldn't have access to them using the interface. But, if you needed them to implement the interface methods, you could do that.
 
Share this answer
 
Have you looked into Dependency Injection as a simpler solution Unity - Dependency Injection
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900