在运行时动态更改对dll的引用 [英] Dynamically changing a reference to a dll at run time

查看:106
本文介绍了在运行时动态更改对dll的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目,正在向摄像机发送命令以控制其菜单.我已经创建了2个dll. 1个用于品牌A,另一个用于品牌B,并且需要其他品牌.

我想将dll作为选项出售,以向软件添加功能,在加载时,它会扫描这些dll的存在并将其添加到组合框.

在我的代码中,我可以创建对dll的引用,并在设计时按如下方式对其进行引用,并且可以正常工作,但是我无法确定如何填充组合框(第二个问题)并允许用户从下拉框中进行选择其他协议并加载它的dll(主要问题).

Dim mProtocol As New CameraAProtocol.Protocol
DLL代码:

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:

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

推荐答案

对于您的主要问题,您正在寻找的是Assembly.LoadFrom方法.据推测,它们内部都将具有相同的方法.我将创建一个接口类,并让您的所有其他类实现该接口.然后,您可以根据接口编写方法.然后,当他们选择使用的摄像机时,只需创建对象的实际实例即可.

大概,该接口将具有一个名为CameraBrand的属性或类似的属性.要获取dll的列表,您可以将它们存储在允许使用不同文件路径的注册表中,也可以强制将它们存储在特定位置.但是,无论哪种方式,您都将寻找不同的dll,然后使用接口类来拉出相机品牌并以这种方式填充组合框.

我从来不需要做这样的事情,但这就是我的开始.我不能保证这会起作用,但是再次,这就是我要开始的地方.
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.


所以,这就是我所做的...(这将是很长的答案)

我在VS中创建了一个解决方案,仅用于制作dll.在该解决方案中,我从Interface开始.看起来像:
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:
Public Interface CameraInterface
    ReadOnly Property Brand As String
    ReadOnly Property Version As String
    ReadOnly Property Model As String
    Function FullInformation() As String
End Interface


然后,我在该解决方案中创建了3个其他项目...一个用于其他类型的相机.在那些项目中,我将引用添加到InterfaceClass(对于CameraInterfacenamespace).然后,在课堂上,我实现了接口.看起来像:


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:

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



一旦创建了这些类,就可以构建dll.

从那里,我创建了一个用于测试界面的新解决方案.再次,我添加了对InterfaceClass的引用.我用菜单创建了一个简单的表单.第一个菜单项是我的LoadFiles ToolStripMenuItem.我创建了一个简单的表单,允许用户选择要加载的文件,然后将它们复制到我设置的目录中.

另一个菜单项仅列出已加载的不同dll.要加载dll,我首先查找目录,然后获取目录中的文件并查找dll.我有一个程序集数组,用于存储每种相机类型.当我添加一个新的dll时,我增加了数组并从文件中创建了一个新的数组.然后,我必须查看该数组中是否存在可以用于接口的类型.为此,我循环浏览程序集中的类型,并检查它是否具有我们需要的接口.如果是这样,我将创建该类型的新实例并创建一个新的菜单项. LoadDlls方法如下所示:



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:

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



您将必须跟踪哪种类型来自哪个程序集以及该程序集中的哪种类型,但是您可以使用该信息创建一个简单的结构,并将该结构添加到菜单项的tag属性中.然后,您可以在需要使用它的任何时间轻松地找到正确的程序集和正确的类型.

至于嵌套类,我不确定还是您正在做什么.我相信您可以根据需要在一个接口中拥有尽可能多的嵌套类.但是您将无法使用该界面访问它们.但是,如果需要它们来实现接口方法,则可以这样做.



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.


您是否已将Dependency Injection作为一种更简单的解决方案进行了研究
Have you looked into Dependency Injection as a simpler solution Unity - Dependency Injection


这篇关于在运行时动态更改对dll的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆