Hallo,
ich versuche, eine Assembly mittels Reflection zur Laufzeit nachzuladen.
System.Reflection.Assembly.Load("Core.dll");
funktioniert nicht, da ich keinen starken Namen bereitstelle. Die Methode LoadWithPartialName ist in .NET 2.0 aber obsolet, was also tun?
Viele Grüße,
der Eisbär
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
Load() will den Assembly-Namen, LoadFrom() den Filenamen.
Okay ... manchmal sieht man den Wald vor lauter Bäumen nicht.
Nun noch eine letzte Frage dazu - ich möchte nun ein Objekt einer Klasse aus dieser Assembly instanziieren, und dort eine bestimmte Methode aufrufen.
Mein Code sieht erst mal folgendermaßen aus:
Assembly coreAssembly = Assembly.LoadFrom("Core.dll");
object core = coreAssembly.CreateInstance("Core.Core");
core.Run();
Bis zu Zeile zwei klappt auch alles, nur gibt es natürlich keine Run-Methode auf dem Datentyp object ... kann mir jemand einen Tipp geben, wie ich an dieses Thema überhaupt herangehe?
Danke,
Golo
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
Du musst den Rückgabewert noch casten, dann hast Du Deinen Type ( wenn alles gut geht 😉 ).
Wobei um den Type zu casten muss er ja bekannt sein... ergo muss das Assembly referenziert sein....
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Ich Vollid..., hast natürlich Recht.
Dann kannste evtl. über Interfaces gehen, weiß ja nicht was Du machen willst.
Noodles' Idee war auch meine, nur tja .... wie mache ich den Typ bekannt, OHNE die DLL zu referenzieren?
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
Die Idee mit dem Cast macht nur Sinn wenn z.B: ein implementiertes Interface .... oder die BaseClass des Objektes direkt referenziert ist (z.B: Plugin-Konzept)
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Ich sage mal, Microkernel. Such mal hier, dass hatten wir schon mehrmals.
Bei meiner Anwendung mach ichs auch über Interfaces. Du estellst dir eine Klassenbibliothek mit den Interfaces. Die Typen in deiner nachzuladenen Bibliothek müssen jetzt dieses Interface implementieren. Nun kannst du in deiner Anwendung die KLassenbibliothek mit den Interfaces direkt refenrenzieren und deine anderen Klassenbiliothek nachladen und dann den Typ casten und dann kannst die Interfacefunktionen ja benutzen um mit dem Objekt zu arbeiten ohne die Klasse des Objektes kennen zu müssen.
Baka wa shinanakya naoranai.
Mein XING Profil.
Definiere ein Interface, welche von der PlugIn-Klasse implementiert wird. Das Interface (nur das!) in eine eigene DLL packen und sowohl von Aufrufer, als auch vom PlugIn referenzieren. Ist der Name des Typen bekannst (z.B. PlugIn-Konfig-XML-File), dann direkt das Obejkt erzeugen und auf das Interfaces casten.
Alternativ kannst du auch alle Typen des PlugIns via Reflection abiterieren und prüfen, ob sie das Interface implementieren, dann weiter wie oben (Problem: Was ist wenn mehrere Klassen das Interface implementieren?).
In meinen Augen noch besser ist der Einsatz von Factory-Objekten/Interfaces im PlugIn. Man holt zunächst eine Factory aus dem Plugin, welches dann die weiteren Objekte (wieder nur via Interfaces zugegriffen) erzeugt. Das entspricht dann in etwa der Erzeugung via CreateInstance mit Parametern (der Activator ist ja eine Abstract Factory-Implementierung), nur findet hier schon die Typrüfung zur Compile-Zeit statt und nicht erst zu Laufzeit (wegen object[]).
Hallo,
ich fand den MSDN Mag - Artikel recht intressant zu dem Thema. Hatte leider bisher noch nicht die Chance Spring.Net mal auszuprobieren.
cu, tb
Hallo,
so, eine erste Lösung habe ich nun - wie unter http://www.des-eisbaeren-blog.de/Default.aspx?Guid=d618811a-52fc-4b20-a599-fe370e957286 beschrieben.
Any comments?
Viele Grüße,
der Eisbär
PS: Ja, ich weiß, dass da Kommentare fehlen ^^
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
Hallo,
ja ich hätte ne kleine Anmerkung. Ich weiß nicht ob ich grad aufm Schlauch stehe, aber was würde passieren wenn man das ganze ohne Reflection löst? Die dll heißt immer gleich. Die Klasse heißt immer gleich. Ist .Net wirklich so intelligent den unterschied zu erkennen wenn dort auf einmal eine andere DLL liegt als vorher? (Von Strong-Names mal abgesehen).
Denn das ist doch imho das gleiche Prinzip wie mit herkömmlichen DLLs. Ändert man nur eine davon, tauscht man diese einfach aus. Und alles funktioniert bestens.
Falls ich den Kernpunkt deines Artikels überlesen habe, mögest du mirs verzeihen.
cu, tb
Hallo,
Du hast natürlich recht, solange die DLL und die Klasse eh immer gleich heißen, hält sich der Sinn in Grenzen ... ich habe gestern noch einiges weiter entwickelt, und das ganze per XML-Datei dynamisch steuerbar gestaltet, und auch gleich noch eine Komponenten-Factory mit dazu gebastelt, die alledings noch ausgebaut werden soll, zum Beispiel um Singleton-Funktionalität.
Den Anfang habe ich nun aber geschafft (danke hier deshalb noch mal an alle, die mir Tipps gegeben haben), der weitere Code wird noch folgen 😉.
Viele Grüße,
Golo
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
Das Spiel kann man ja noch beliebig weiter treiben. Mein Programm arbeitet ähnlich, nur das ich halt alle meine nachgeladenen Dll's in ne extra AppDomain lade, dort ShadowCopy aktiviert habe, und mir nen FileSystemWatcher drauf gelegt habe der mir Änderungen verfolgt an den Dll's. Nun kann ich wenn die Anwendung läuft einfach neue Versionen ins Plugin Verzeichnis bei mir kopieren, der lädt die neu, und beim nächsten Benutzen einer Funktion wird die neue Dll benutzt. Und das beste: der Anwender bekommt gar nichts mit 🙂 Das ganze Assembly konzept in .Net ist schon recht clever find ich.
Baka wa shinanakya naoranai.
Mein XING Profil.
*gg* .... die Idee hat was 😉
Ist das privater Code von Dir, den Du bereit wärst, weiterzugeben? Würde da gerne mal ein bisschen drin stöbern, einfach, um auch bissle was dabei zu lernen.
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
So, es gibt ein kleines Update - siehe http://www.des-eisbaeren-blog.de ... Komponenten werden nun aus eienr XML-Datei geladen und das ganze funktioniert nicht nur mit der Application-DLL, sondern mit beliebigen Komponenten 🙂
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
Hab grad deinen Blog gelesen 😉 brauchst du das Beispiel noch? Also so wie ich es momentan verwende kann ichs dir eh leider nicht überlassen, aber könnte dir ne kleine "Technologiedemo" zeigen wo ich das in den Anfängen mal selber ausprobiert habe wie das funktioniert.
Gruß Talla
Baka wa shinanakya naoranai.
Mein XING Profil.
🙂
Also, ich denke schon, dass es mir helfen würde, zu sehen, wie Du daran gegangen bist. Und so eine Technologiedemo klingt doch schon mal recht gut 🙂.
Von dem her, wenn Du mir da was zeigen kannst, sehr gerne 🙂
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden
Original von talla
Hab grad deinen Blog gelesen 😉 brauchst du das Beispiel noch? Also so wie ich es momentan verwende kann ichs dir eh leider nicht überlassen, aber könnte dir ne kleine "Technologiedemo" zeigen wo ich das in den Anfängen mal selber ausprobiert habe wie das funktioniert.Gruß Talla
Hallo Talla, ist das Angebot noch Aktuell? Ich würde gerne mal reinschauen! Habe mich den ganzen Tag mit AppDomains und Setups herumgeschlagen, aber irgendwie komme ich auf keinen grünen Zweig 🙁
Ich möchte mein Problem ein wenig ausführlicher beschreiben:
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
setup.PrivateBinPath = "Plugin";
setup.ShadowCopyFiles = "true";
AppDomain app = AppDomain.CreateDomain("PluginDomain", AppDomain.CurrentDomain.Evidence, setup);
ArrayList assemblies = new ArrayList(app.GetAssemblies());
ArrayList plugins = new ArrayList();
foreach(Assembly asm in assemblies) {
plugins.AddRange(GetPlugin(asm));
}
foreach(IPlugin p in plugins)
Console.WriteLine("Plugin: " + p.Name);
setup.ApplicationBase ist das Verzeichnis in dem ich die Anwendung startete. Dort habe ich einen Unterordner "Plugin" in welchem ich eine Assembly habe. Doch die ArrayList assemblies hat nur eine Assembly drin, die mscorlib.dll! Warum? Ich blicke nicht durch...
Hoffe ihr könnt mir helfen 🙂
LG Michi