.NET Komponenten (DLLs) dynamisch während der Laufzeit einbinden

Fr, 23.04.2010 - 18:43 -- admin

Viele Programme lassen sich durch DLL Dateien erweitern. In .NET kann man zwar per Verweis auf externe Datei zugreifen, jedoch kann man nicht während der Programmlaufzeit deine bestimmte Methode und Funktion einer bestimmten externen Datei ausführen. So wäre es doch sinnvoll nach dem Programmstart ein Unterverzeichnis z.B. Addins nach Dateien zu durchsuchen und die dort enthaltenen Funktion auszulesen. So kann man relativ einfach ohne neues kompilieren der Hauptanwendung Änderungen an den Addins vornehmen oder diese komplett entfernen.

.NET bring eigentlich alles von Haus aus mit, was zwar erst etwas umständlich aussieht, aber nach erstellen einer einfachen benutzerdefinierten Klassen kann man schon mit recht einfachen Mittel einiges Bewegen.

Beispiele

Neben der AddinDLLReader Klasse, welche den Zugriff auf eine fremde .NET DLL erlaubt, habe auch eine beispielhafte Klassenbibliothek erstellt, welche in einer DLL gespeichert wird. Zum Einbinden der Datei muss man deren Namespace kennen, die Klassen macht diesem zum Teil von alleine, wie man im Quelltext erkennen kann.
Innerhalb der Klassen kann man nun bestimmte Methoden suchen oder gezielt eine Methode aufrufen. Den Rückgabe der Methode kann man entsprechende seinen Wünschen anpassen / konvertieren.

VCS File: 

/trunk/AddinDLLReader/Example.vb

'$Id: Example.vb 22 2010-03-25 13:44:43Z espendiller $
'$HeadURL: file:///var/svn-repos/vbnettools/trunk/AddinDLLReader/Example.vb $'
 
Module Example
 
    Sub Main()
        'Our DLL has the Namespace ExampleDLL.TheClass, ExampleDLL ist generated automatically out of the filename
        Dim Addin As New AddinDLLReader("ExampleDLL.dll", "TheClass")
 
        'Some ready functions
        Console.WriteLine("Description: " & Addin.Description)
        Console.WriteLine("Version: " & Addin.Version)
 
        'call a known function that returns a ArrayList
        Console.WriteLine(vbNewLine & "GetExtension; returns ArrayList:")
        For Each Ext In Addin.RunMethod("GetExtension")
            Console.WriteLine(Ext)
        Next
 
        'show all function / sub of the class
        Console.WriteLine(vbNewLine & "The class contains this methodes:")
        For Each Met In Addin.GetMethodes
            Console.WriteLine(Met)
        Next
 
        'check if the class has a given function
        Console.WriteLine(vbNewLine & "checking if function/sub exists")
        If Addin.GetMethodes.Contains("Version") Then
            Console.WriteLine("Function ´Version´ was found")
        End If
 
        'call a function with a paramter
        Console.WriteLine(vbNewLine & "We are calling FunctionWithParamter with a single paramter:")
        Console.WriteLine("returns: " & Addin.RunMethod("FunctionWithParamter", New Object() {"MyParamter"}))
 
        Console.ReadKey()
 
 
        'the code above gave you this output
        'Description: Wow a Description at: 25.03.2010 14:31:36
        'Version: 1.0.0.0
 
        'GetExtension; returns ArrayList:
        '        pdf()
        '        doc()
 
        'The class contains this methodes:
        '        GetExtension()
        '        Version()
        '        Description()
        '        FunctionWithParamter()
 
        'checking if function/sub exists
        'Function ´Version´ was found
 
        'We are calling FunctionWithParamter with a single paramter:
        'returns: You gave me a nice paramter: MyParamter
 
    End Sub
 
End Module

/trunk/AddinDLLReader/ExampleDLL.vb

'$Id: ExampleDLL.vb 22 2010-03-25 13:44:43Z espendiller $
'$HeadURL: file:///var/svn-repos/vbnettools/trunk/AddinDLLReader/ExampleDLL.vb $
 
Public Class TheClass
    Function GetExtension() As ArrayList
        Dim Ext As New ArrayList
        Ext.Add("pdf") : Ext.Add("doc")
        Return Ext
    End Function
    Function Version() As String
        Return My.Application.Info.Version.ToString()
    End Function
    Function Description() As String
        Return "Wow a Description at: " & Now
    End Function
    Function FunctionWithParamter(ByVal paramter As String) As String
        Return "You gave me a nice paramter: " & paramter
    End Function
End Class

/trunk/AddinDLLReader/AddinDLLReader.vb

'$Id: AddinDLLReader.vb 22 2010-03-25 13:44:43Z espendiller $
'$HeadURL: file:///var/svn-repos/vbnettools/trunk/AddinDLLReader/AddinDLLReader.vb $
 
Imports System.Reflection
''' <summary>
''' A class that can dynamically include a remote .NET Framework dll
''' and call some functions at application runtime
''' 
''' You must known the Namespace of the remote file to include it.
'''
''' ExampleDLL.dll gives you ´ExampleDLL.TheClass´
'''  - ExampleDLL will autogenerated out of the filename
'''  - You only had to give the correct ClassName (TheClass)
''' </summary>
''' <remarks></remarks>
Class AddinDLLReader
    Private _aAssembly As [Assembly]
    Private _aClass As Type
    Private _aAddin As Object
    Private _File As System.IO.FileInfo
    Private _AssemblyName As String
 
    ''' <summary>
    ''' </summary>
    ''' <param name="FullDLLAddinPath">The path to the DLLFile</param>
    ''' <param name="ClassName">The Classname of the remote dll: ´ExampleDLL.TheClass´ = TheClass</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal FullDLLAddinPath As String, ByVal ClassName As String)
        _File = New System.IO.FileInfo(FullDLLAddinPath)
        _AssemblyName = Replace(_File.Name, _File.Extension, "")
 
        'the magic stuff: include and read a external dll 
        _aAssembly = Reflection.Assembly.LoadFile(_File.FullName)
        _aClass = _aAssembly.GetType(_AssemblyName & "." & ClassName)
        _aAddin = Activator.CreateInstance(_aClass)
 
    End Sub
    ''' <summary>
    ''' Returns a ArrayList with all Methodes of the class
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function GetMethodes() As ArrayList
        Dim bArray As New ArrayList
        For Each k In _aClass.GetMethods()
 
            'hide unwanted: ToString, Equals, GetHashCode, GetType
            If k.IsHideBySig = False Then
                bArray.Add(k.Name)
            End If
        Next
        Return bArray
    End Function
 
    ''' <summary>
    ''' Run a given Method (eg. Function / Sub). You can pass any paramter as a object: New Object() {"MyParamter"}
    ''' </summary>
    ''' <param name="Method">Function / Sub to call</param>
    ''' <param name="Paramter">A object containing the paramter</param>
    ''' <returns>return value of the called function as object</returns>
    ''' <remarks></remarks>
    Function RunMethod(ByVal Method As String, Optional ByVal Paramter() As Object = Nothing) As Object
        'New Object() {"1111"}
        Dim aMethode As MethodInfo = _aClass.GetMethod(Method)
        Return aMethode.Invoke(_aAddin, Paramter)
    End Function
    ''' <summary>
    ''' Returns the filename of the DLL
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property DLLName() As String
        Get
            Return _File.Name
        End Get
    End Property
    ''' <summary>
    ''' Returns the FullPath of the DLL that were given by New()
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property FullPath() As String
        Get
            Return _File.FullName
        End Get
    End Property
    ''' <summary>
    ''' Returns the AssemblyName that was automatically generated
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property AssemblyName() As String
        Get
            Return _AssemblyName
        End Get
    End Property
    ''' <summary>
    ''' Example: Calls the function Version of the dll class
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property Version() As String
        Get
            Return RunMethod("Version").ToString
        End Get
    End Property
    ''' <summary>
    ''' Example: Calls the function Description of the dll class
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property Description() As String
        Get
            Return RunMethod("Description").ToString
        End Get
    End Property
End Class