.Net Dynamisch DLL Laden

Ich versuche, code zu schreiben, dass wird mir erlauben, das dynamische laden von DLLs in meiner Anwendung, je nach Anwendung einstellen. Die Idee ist, dass die Datenbank auf die zugegriffen wird, in den Programmeinstellungen und dann dieser lädt die entsprechende DLL, und ordnet es zu einer Instanz einer Schnittstelle für meine Anwendung zugreifen.

Dies ist mein code im moment:

        Dim SQLDataSource As ICRDataLayer
    Dim ass As Assembly = Assembly. _
    LoadFrom("M:\MyProgs\WebService\DynamicAssemblyLoading\SQLServer\bin\Debug\SQLServer.dll")

    Dim obj As Object = ass.CreateInstance(GetType(ICRDataLayer).ToString, True)
    SQLDataSource = DirectCast(obj, ICRDataLayer)

    MsgBox(SQLDataSource.ModuleName & vbNewLine & SQLDataSource.ModuleDescription)

Habe ich mein interface (ICRDataLayer) und die SQLServer.dll enthält eine Implementierung dieser Schnittstelle. Ich will einfach nur, um die assembly zu laden und weisen Sie es dem SQLDataSource-Objekt.

Der obige code funktioniert einfach nicht. Es gibt auch keine exceptions geworfen, auch die Msgbox nicht angezeigt.
Ich hätte erwartet, dass zumindest die messagebox erscheinen mit nichts drin, aber auch das ist nicht passiert!

Gibt es eine Möglichkeit zu bestimmen, ob die geladene assembly implementiert eine bestimmte Schnittstelle. Ich habe versucht, das unten, aber das scheint auch nicht, etwas zu tun!

        For Each loadedType As Type In ass.GetTypes
        If GetType(ICRDataLayer).IsAssignableFrom(loadedType) Then
            Dim obj1 As Object = ass.CreateInstance(GetType(ICRDataLayer).ToString, True)
            SQLDataSource = DirectCast(obj1, ICRDataLayer)
        End If
    Next

EDIT: Neuer code von Vlad Beispiele:

    Module CRDataLayerFactory
    Sub New()
    End Sub
    ' class name is a contract,
    ' should be the same for all plugins
    Private Function Create() As ICRDataLayer
        Return New SQLServer()
    End Function
End Module

Oben ist das Modul in jeder DLL, Umgerechnet aus Vlad ' s C# Beispiel.

Unten ist mein code zu verwenden, um die in der DLL:

Dim SQLDataSource As ICRDataLayer
    Dim ass As Assembly = Assembly. _
    LoadFrom("M:\MyProgs\WebService\DynamicAssemblyLoading\SQLServer\bin\Debug\SQLServer.dll")

    Dim factory As Object = ass.CreateInstance("CRDataLayerFactory", True)
    Dim t As Type = factory.GetType
    Dim method As MethodInfo = t.GetMethod("Create")
    Dim obj As Object = method.Invoke(factory, Nothing)
    SQLDataSource = DirectCast(obj, ICRDataLayer)

EDIT: Implementierung, basierend auf Paul Kohler-code

Dim file As String
        For Each file In Directory.GetFiles(baseDir, searchPattern, SearchOption.TopDirectoryOnly)
            Dim assemblyType As System.Type
            For Each assemblyType In Assembly.LoadFrom(file).GetTypes

                Dim s As System.Type() = assemblyType.GetInterfaces
                For Each ty As System.Type In s

                    If ty.Name.Contains("ICRDataLayer") Then
                        MsgBox(ty.Name)
                        plugin = DirectCast(Activator.CreateInstance(assemblyType), ICRDataLayer)
                        MessageBox.Show(plugin.ModuleName)
                    End If
                Next

Bekomme ich die folgende Fehlermeldung mit diesem code:

Unable to cast object of type 'SQLServer.CRDataSource.SQLServer' to type 'DynamicAssemblyLoading.ICRDataLayer'.

Die DLL in einem anderen Projekt namens SQLServer in die gleiche Lösung wie meine Implementierung code. CRDataSource ist ein namespace und SQLServer ist die eigentliche Klasse name der DLL.
Der SQLServer-Klasse implementiert ICRDataLayer, so verstehe ich nicht, warum es nicht in der Lage sein, um Sie zu wirken.
Ist die Namensgebung hier von Bedeutung wäre, wäre ich nicht dachte, es wäre.


Endgültige code

Inhalt PluginUtility:

enter code here    Public Shared Function GetInstances1(Of Type)(ByVal baseDir As String, ByVal searchPattern As String) As System.Type()
    Dim tmpInstances As New List(Of Type)
    Try
        Dim file As String
        For Each file In Directory.GetFiles(baseDir, searchPattern, SearchOption.TopDirectoryOnly)
            Dim assemblyType As System.Type
            For Each assemblyType In Assembly.LoadFrom(file).GetTypes

                Dim s As System.Type() = assemblyType.GetInterfaces
                Return s.ToArray()

            Next
        Next
    Catch exp As TargetInvocationException
        If (Not exp.InnerException Is Nothing) Then
            Throw exp.InnerException
        End If
    End Try
End Function

Code zum laden der DLL:

enter code here
    Dim basedir As String = "M:\MyProgs\WebService\DynamicAssemblyLoading\SQLServer\bin\Debug\"
    Dim searchPattern As String = "*SQL*.dll"
    Dim plugin As CRDataLayer.ICRDataLayer

    Try
        Dim file As String
        For Each file In Directory.GetFiles(baseDir, searchPattern, SearchOption.TopDirectoryOnly)
            Dim assemblyType As System.Type
            For Each assemblyType In Assembly.LoadFrom(file).GetExportedTypes

                If assemblyType.GetInterface("CRDataLayer.ICRDataLayer") IsNot Nothing Then
                    plugin = DirectCast(Activator.CreateInstance(assemblyType), CRDataLayer.ICRDataLayer)
                    MessageBox.Show(plugin.ModuleDescription)
                End If

            Next
        Next
    Catch exp As TargetInvocationException
        If (Not exp.InnerException Is Nothing) Then
            Throw exp.InnerException
        End If
    Catch ex As Exception
        MsgBox(ex.Message)
        Clipboard.SetText(ex.Message)
    End Try
  • Verwenden Sie nicht ty.Name.Contains("ICRDataLayer") - überprüfen, dass es "implementiert den Typ" mit assemblyType.GetInterface("your namespace etc.ICRDataLayer") (siehe http://msdn.microsoft.com/en-us/library/tcctb9t8.aspx) es wird Ihnen Nothing wenn Ihr nicht implementiert, indem der aktuelle Typ. Auch, die Ausnahme scheint, um anzuzeigen, dass die Schnittstelle nicht implementiert, verwenden Sie eine gemeinsame DLL für diese - es muss der gleiche. PK
  • Überprüfen Sie die Lösung unten wieder...
  • Es funktioniert! Ich landete mit Ihrem code Paul, es funktioniert genau so, wie ich es brauche. Für alle, die kommen können, über diesen thread in der Zukunft, ich will hinzufügen, meine Letzte code in der original-Beitrag, so hoffentlich können Sie haben eine einfachere Zeit bekommen, diese arbeiten als ich. Danke allen für Ihre Hilfe
InformationsquelleAutor hermiod | 2010-03-01
Schreibe einen Kommentar