AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Klassenbiliothek (DLL) dynamisch Laden ?
Thema durchsuchen
Ansicht
Themen-Optionen

Klassenbiliothek (DLL) dynamisch Laden ?

Ein Thema von slemke76 · begonnen am 12. Jun 2007 · letzter Beitrag vom 5. Jul 2007
Antwort Antwort
slemke76

Registriert seit: 29. Mär 2005
Ort: Quakenbrück
146 Beiträge
 
#1

Klassenbiliothek (DLL) dynamisch Laden ?

  Alt 12. Jun 2007, 18:06
Hallo zusammen,

ich schreibe etwas "artfremd", aber ich möchte gerne eine Kleinigkeit in .NET - genauer VB.NET - realisieren. Da ich bis jetzt kein gutes .NET Forum gefunden habe, schreibe ich hier - bitte nicht steinigen

Also - ich habe eine Klassenbibliothek, die mit .NET kompiliert ist. Diese möchte ich gerne dynamisch aus einer anderen .NET Anwedung laden. "Statisch" funktioniert dies bereits, die DLL ist unter "Verweise" eingebunden und im Source entsprechend
Code:
Imports MyBaseClass
aufgerufen. Wie gesagt - klappt alles.

Hintergrund ist, daß ich nach Start der Anwendung die Existenz der DLL prüfen möchte (im gleichen Verzeichnis wie die Anwendung) um dann entsprechend darauf zu reagieren.

Kann mir jemand einen Tip geben ?

mfg
Sebastian
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#2

Re: Klassenbiliothek (DLL) dynamisch Laden ?

  Alt 12. Jun 2007, 18:28
Hi,
ich glaube zwar nicht, dass es direkt was mit der API zu tun hat (hier solltest Du denke ich um das Verschieben durch einen Moderator bitten), aber Steine habe ich auch keine bei.

Versuch es mal damit:

Code:
assem = System.Reflection.Assembly.Load(....)
obj = assem.CreateInstance("<Klassentyp>")
Obj musst Du natürlich noch entsprechend casten, da Du hier nur ein Object bekommst, aber grob sollte es (ungetestet, bin kein VB.netler) in der Richtung funktionieren.

Gruß Der Unwissende
  Mit Zitat antworten Zitat
slemke76

Registriert seit: 29. Mär 2005
Ort: Quakenbrück
146 Beiträge
 
#3

Re: Klassenbiliothek (DLL) dynamisch Laden ?

  Alt 14. Jun 2007, 17:41
Hallo,

Zitat von Der_Unwissende:
aber Steine habe ich auch keine bei.
Dann bin ich beruhigt.
Du hast mich auf alle Fälle schonmal auf die Fährte gesetzt.

Ich komme jetzt aber partout nicht weiter

Folgende Klassenbibliothek:

Code:
Imports System
Namespace MyAssembly
    Public Class Maths
        Public Function Add(ByVal numberOne As Integer, ByVal numberTwo As Integer)
            Return numberOne + numberTwo
        End Function
    End Class
End Namespace
Ich habe mir jetzt gedacht, ich mache eine Konsolenanwendung, in der ich "einfach" nur die "Add" Funktion aufrufe:

Code:
Imports System
Imports System.Reflection

Module Module1

    Sub Main()
        Dim asm As Assembly = Assembly.LoadFrom("<Pfad>\MyAssembly.dll")

        Console.WriteLine("Types des Klassenbiliothek:")
        Dim typeArray As Type()
        typeArray = asm.GetTypes()

        Dim MonType As Type
        For Each MonType In typeArray
            Console.WriteLine("Type : " + MonType.Name)
        Next

        ' *** Jetzte Speziell für Type "Maths" abrufen
        Dim typeSingle As Type
        typeSingle = asm.GetType("Maths")
        If (typeSingle Is System.DBNull.Value) Then
            Console.WriteLine("typeSingle ist leer ?!")
        End If
        Dim t2 As MemberInfo() = typeSingle.GetMembers()   ' Hier kommt immer der Fehler :-(

    End Sub

End Module
Bis zu Dim t2 As MemberInfo() funktioniert auch alles. Die Fehlermeldung "typeSingle ist leer ?!" kommt NICHT.
In der besagten Zeile bricht der Compiler mit "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt." ab.
Das kann doch nur eine Banalität sein - aber ich komm nicht drauf. Probiert (wie ich "probieren" beim programmieren hasse) habe ich auch schon die typeSingle Zuweisung wie folgt zu ändern:
Code:
typeSingle = asm.GetType("MyAssembly.Maths")
oder
Code:
typeSingle = asm.GetType("MyAssembly")
Gleiche Meldung. Entwicklungsumgebung ist VS2005.
Achso: In der Ausgabe von "Console.WriteLine("Type : " + MonType.Name)" ist "Maths" enthalten.

Zweifel langsam an mir selbst, das kann doch nicht so wild sein ?!

Grüße,
Sebastian
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#4

Re: Klassenbiliothek (DLL) dynamisch Laden ?

  Alt 14. Jun 2007, 17:54
Obwohl du VB benutzt, will ich mal trotzdem was dazu schreiben[1].

Ich werde es in C# schreiben, sollte aber nachvollziehbar sein.

Man nehme 2 Assemblies.
Eine nennen wir einfach mal PluginRtl, die andere PluginLib.
In die PluginRtl packen wir ein Interface, welches durch die eigentliche Klasse im eigentlichen Plugin implementiert wird.
Warum erkläre ich später.

Die erste Assembly enthält nur das hier:
Code:
namespace PluginRtl
{
  public interface IMathDings
  {
    int Add(int left, int right);
  }
}
Die zweite Assembly setzt eine Referenz auf die erste und implementiert das Interface:
Code:
namespace PluginLib
{
  public sealed class MathDings : IMathDings
  {
    public int Add(int left, int right)
    {
       return left + right;
    }
  }
}
So nun noch schnell eine kleine Anwendung erzeugt, die wiederum die erste Assembly referenziert:
Code:
class Program
{
  static void Main()
  {
    Assembly plugin = Assembly.LoadFile("PluginLib.dll");
    Type mathDingsType = plugin.GetType("PluginRtl.MathDings");
    if(typeof(IMathDings).IsAssignableForm(mathDingsType))
    {
       IMathDings instance = Activator.CreateInstance(mathDingsType) as IMathDings;
       int result = instance.Add(1, 2);
    }
  }
}

Ist aber alles uncompiliert aus den Fingern gesaugt. Kleinere Ecken können also drin, aber es sollte trotzdem die Herangehensweise klar machen.
Das Interface in einer eigene Assembly hat den Grund, dass man so eine Stelle hat, gegen die man kompilieren kann, aber trotzdem noch die Implementierung wechseln kann.





[1] Vielleicht wirst du ja gezwungen und kannst nix dafür...
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
slemke76

Registriert seit: 29. Mär 2005
Ort: Quakenbrück
146 Beiträge
 
#5

Re: Klassenbiliothek (DLL) dynamisch Laden ?

  Alt 14. Jun 2007, 19:31
Hallo,

erstmal vielen Dank für deine superschnelle Antwort.

Zitat von Elvis:
Obwohl du VB benutzt, will ich mal trotzdem was dazu schreiben[1].
Die Fussnote ist nicht schlecht Jaein - ich will etwas vorhandenes weiterentwickeln....

Ich habs leider nicht hinbekommen, ich dreh langsam durch...

Also - Klassenbibliothek mit folgenden Inhalt erstellt:

Code:
Namespace PluginRtl
    Public Interface IMathDings
        Function Add(ByVal left As Integer, ByVal right As Integer) As Integer
    End Interface
End Namespace

Namespace PluginLib
    Public Class MathDings
        Implements PluginRtl.IMathDings
        Public Function Add(ByVal left As Integer, ByVal right As Integer) As Integer Implements PluginRtl.IMathDings.Add
            Return left + right
        End Function
    End Class
End Namespace
Hoffe, daß das alles korrekt ist. DLL wird ohne Fehler erstellt.

Jetzt gibt es wieder Probleme im Hauptprogramm - zunächst habe ich die typeof-Passage noch nicht umgesetzt. Da es nur eine If-Bedingung ist, habe ich das erstmal vernachlässigt. Das CreateInstance schlägt fehlt (wobei mir im übrigen die korrekte Syntax unter VB.NET nicht klar ist).
Schliesslich habe ich es soweit reduziert:
Code:
Imports System.Reflection
Module Module1
    Sub Main()
        Dim plugin As Assembly = Assembly.LoadFrom("<Pfad>\PluginLib.dll")
        Dim mathDingsType As Type = plugin.GetType("PluginRtl.MathDings")
        Activator.CreateInstance(mathDingsType)
    End Sub
End Module
Müsste das nicht eigentlich zumindest sauber abgearbeitet werden (auch wenn ich mit der Instanz nix anstellen kann, weil das Ergebniss von .CreateInstance nicht in einer Variable gespeichert wird) ? Es kommt nämlich die Meldung "Der Wert darf nicht NULL sein." bei .CreateInstance (die Meldung in meinem zweiten Post ist ja ähnlich).

Nochmal etwas grundsätzliches:
Wo liegt denn eigentlich der praktische Unterschied, ob ich mit CreateInstance - wie aus deinem Beispiel - oder ohne - wie aus meinem zweiten Posting - arbeite ?

Vielen Dank für Eure Geduld.


Sebastian
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#6

Re: Klassenbiliothek (DLL) dynamisch Laden ?

  Alt 14. Jun 2007, 20:20
Zitat von slemke76:
Die Fussnote ist nicht schlecht Jaein - ich will etwas vorhandenes weiterentwickeln....
Na dann aber Vorsicht. Du wirst schon langsam zu einem richtigen VB'ler.
Die Klasse heißt PluginLib.MathDings, nicht PluginRtl.MathDings.
Und immer schön dran denken:
Die Interfaces/Klassen , die du in Anwendung und PlugIns benutzen willst, müssen in eine getrennte Assembly gepackt werden.
Diese kann dann von Anwendung und Plugins benutzt werden.
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
slemke76

Registriert seit: 29. Mär 2005
Ort: Quakenbrück
146 Beiträge
 
#7

Re: Klassenbiliothek (DLL) dynamisch Laden ?

  Alt 5. Jul 2007, 19:15
Hallo,

so ich habe mich recht weit "durchgebissen".
Ich habe anfangs etwas (nach wie vor) an "GetType" gehangen, bis ich den .Fullname angegeben habe (passiert auch nur ein mal )

Zitat von Elvis:
Die Interfaces/Klassen , die du in Anwendung und PlugIns benutzen willst, müssen in eine getrennte Assembly gepackt werden.
Das war einer meiner Fehler. Ich habe das Interface und die Klasse in einer Assembly (aber getrennte Namespaces). Wenn ich jetzt

Code:
Dim obj As Object = Activator.CreateInstance(MathClassType)
Dim iType As MyAssembly.IMyAssemblyNS.IMathClass = CType(obj, MyAssembly.IMyAssemblyNS.IMathClass)
aufrufe, dann bekomme ich immer die Meldung "Das Objekt des Typs ... kann nicht in Typ ... (bei der zweiten Anweisung) umgewandelt werden.

Ich würde mir gerne die DLL für das Interface sparen und "einbetten". Aber das wiederspricht ja eigentlich dem Sinn, oder ?
Wenn ich das richtig verstanden habe, dann brauche ich kein Interface schreiben, wenn es sich um eine Assembly handelt, die zwar dynamisch nachgeladen, aber nicht austauschbar sein soll ? Dann würde ich die Funktionen der Klasse direkt ohne Interface ansprechen ?

Alles nicht so einfach Aber ich bin fast am Ziel.

lg
Sebastian
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz