![]() |
MEF: Plugin-Schlittstelle in C#/WPF
Hallo zusammen,
seit Tagen versuche ich vergebens per MEF (Managed Extensibilty Framework) eine Plugin-Schnittstelle zu realisieren. Die Plugins sind DLLs, die entsprechend geladen werden. Relativ schön finde ich z.B. dieses Beispiel: ![]() Am Ende des Beitrags lässt sich der Quellcode herunterladen. Bei mir stimmen alle Pfade und das Programm lässt sich fehlerfrei kompilieren (ich habe es laut Anleitung auch selbst programmiert). Dennoch findet das Programm an folgender Stelle kein passendes Plugin:
Code:
Ich habe es auch mit einem absoluten Pfad versucht. Und
var catalog = new DirectoryCatalog(@"..\..\..\Plugins");
var container = new CompositionContainer(catalog); var pluginRepository = new PluginRepository() { CalculationServices = container.GetExportedValues<ICalculationService>() };
Code:
liefert mir auch die korrekten DLLs. D.h. am Pfad kann es nicht liegen.
Directory.GetFiles()
Leider bleibt "CalculationServices" leer. Eine Fehlermeldung gibt es nicht. Woran kann es liegen, dass die DLLs nicht als gültiges Plugin erkannt werden? Auch mit einer zusätzlichen Export-Angabe funktioniert es nicht:
Code:
Ich verwende aktuell Microsoft Visual C# 2010 Express unter Windows XP mit .NET 4.0.
[Export(typeof(ICalculationService))]
public class Multiply : ICalculationService { public int Calculate(int number1, int number2) { return number1 * number2; } } Grüße Matze |
AW: MEF: Plugin-Schlittstelle in C#/WPF
Geht es Dir um genau diese Lösung, oder irgend eine?
Dann versuch das hier: 1. Das Plugin-Interface IPlugin. Wird von jedem Plugin implementiert. Pro Assembly ein Plugin. Du kannst auch mehrere dort implementieren, aber dann funktioniert der Wrapper weiter unten nicht (kann aber erweitert werden).
Code:
2. Der Plugin-Loader im Hauptprogramm. Sucht nach Assemblies und importiert die, die IPlugin implementieren.
public interface IPlugin
{ string GetName(); string GetDescription(); string GetVersion(); UserControl ConfigurationDialog(); void Execute(); ... }
Code:
Der Plugin-Wrapper:
var directoryInfo = new DirectoryInfo(path);
foreach (var file in directoryInfo.GetFiles("*.dll")) { Wrapper pluginWrapper = new PluginWrapper(file.FullName); if (pluginWrapper.IsValid) { string fullname = pluginWrapper.Instance.GetName() + " " + pluginWrapper.Instance.GetVersion(); ... } }
Code:
Ein Wrapper wird also mit dem vollständigen Pfadnamen der Assembly instantiiert. Der Wrapper prüft, ob eine IPlugin - Klasse in der Assembly vorhanden ist und setzt 'IsValid' auf true, wenn dem so ist. Dann ist über die Property 'Instance' auch eine Instanz der Implementierung abrufbar.
internal class PluginWrapper
{ private readonly IPlugin _pluginInstance; public bool IsValid; public PluginWrapper(string fullFilename) { IsValid = false; Assembly assembly = Assembly.LoadFile(fullFilename); var type = assembly.GetTypes().FirstOrDefault(IsPlugin); if (type == null) return; _pluginInstance = (IPlugin)Activator.CreateInstance(type); IsValid = true; } public IPlugin Instance { get { return _pluginInstance; } } private bool IsPlugin(Type type) { return type.IsClass && type.IsPublic && type.GetInterfaces().Contains(typeof(IPlugin)); } } In dieser Implementierung wird nur die erste IPlugin-Klasse jeder Assembly geladen. Man kann das natürlich erweitern, sodaß alle Klassen geladen werden. Wie Du siehst, habe ich keinerlei Attribute. Ich muß aber ehrlich sagen, daß das so mit mein erstes C#-Projekt war, also kann man das bestimmt noch verbessern. |
AW: MEF: Plugin-Schlittstelle in C#/WPF
Dankeschön, das teste ich mal. :-)
Es wäre jedenfalls wichtig, dass man auch mehrere Plugins parallel laden und nutzen kann. Ich habe im Internet auch ähnliche Lösungen gefunden, nur wurde dann immer auf MEF hingewiesen und dass man damit flexibler sei. Selbst beurteilen kann ich das jedoch nicht. Grüße Matze |
AW: MEF: Plugin-Schlittstelle in C#/WPF
Hassu einmal Build Solution [F6] ausgeführt?
Der Auto hat die Plugins nicht als indirekte Dependencies von MefSimpleDemo eingetragen. MsBuild weiß also gar nicht, dass es die 2 anderen Projekte auch kompostieren muss, wenn es MefSimpleDemo kompiliert. |
AW: MEF: Plugin-Schlittstelle in C#/WPF
Zitat:
|
AW: MEF: Plugin-Schlittstelle in C#/WPF
Zitat:
|
AW: MEF: Plugin-Schlittstelle in C#/WPF
Zitat:
Ungeachtet dessen... Ich habe das: Runtergeladen -> Entpackt -> im VS geöffnet -> F5 -> ging nicht -> F6 -> F5 -> funzt Benutzt du C# Express? Da ist es etwas schwierig die Build-Configs zu verwalten. IMO wird dort ein Build als Release kompiliert und jeder Debug-Run mit der Debug Config. (Komplett Ouchy-Banana, aber mit irgendwelchen blöden Einschränkungen müssen sie einem ja die kostenlose IDE versalzen ;-) ) Das könnte erklären, warum es bei dir nicht geht. Du kannst es per commandline kompilieren...
Code:
oder die Ausgabepfade in den beiden Projekten anpassen.
msbuild MefSimpleDemo.sln /t:Rebuild /p:Configuration=Debug
|
AW: MEF: Plugin-Schlittstelle in C#/WPF
Zitat:
Ich kann mit C# Express schon ein Release-Build generieren, aber der wird nicht als gültige DLL akzeptiert, wie's aussieht. |
AW: MEF: Plugin-Schlittstelle in C#/WPF
Nein Release builds haben eine andere Konfiguration. Also auch einen anderen Ausgabepfad.
Du kannst auch #develop nehmen, das ist nicht so bescheuert wie c# express. |
AW: MEF: Plugin-Schlittstelle in C#/WPF
Danke. Dann teste ich, ob es mit #develop funktioniert.
Kennst du dennoch eine Möglichkeit, das ganze mit Visual C# Express zum Laufen zu bekommen? Vielleicht liegt's nur an einer Einstellung. Nachtrag: Mit #develop ist's das Gleiche. :gruebel: Mir wäre Visual C# Express aber lieber. Nachtrag 2: Ich Duppel. Es funktioniert alles. Das Stichwort "Netzwerk" war der Knackpunkt. Ich nutze eine Virtual Machine und greife über Shared Folders auf den Host zu. Und diese Verzeichnisse werden als Netzlaufwerk eingebunden und darin lag mein Projekt. :wall: Da wäre eine Warnung des Debuggers o.ä. eigentlich angebracht ... Nochmals vielen Dank euch beiden! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz