AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

MEF: Plugin-Schlittstelle in C#/WPF

Ein Thema von Matze · begonnen am 15. Okt 2013 · letzter Beitrag vom 17. Okt 2013
Antwort Antwort
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.987 Beiträge
 
Turbo Delphi für Win32
 
#1

MEF: Plugin-Schlittstelle in C#/WPF

  Alt 15. Okt 2013, 06:33
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: http://stevenhollidge.blogspot.de/20...ef-with-c.html

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:
var catalog = new DirectoryCatalog(@"..\..\..\Plugins");
var container = new CompositionContainer(catalog);
var pluginRepository = new PluginRepository()
{
    CalculationServices = container.GetExportedValues<ICalculationService>()
};
Ich habe es auch mit einem absoluten Pfad versucht. Und
Code:
Directory.GetFiles()
liefert mir auch die korrekten DLLs. D.h. am Pfad kann es nicht liegen.

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:
[Export(typeof(ICalculationService))]
public class Multiply : ICalculationService
{
    public int Calculate(int number1, int number2)
    {
        return number1 * number2;
    }
}
Ich verwende aktuell Microsoft Visual C# 2010 Express unter Windows XP mit .NET 4.0.

Grüße
Matze

Geändert von Matze (15. Okt 2013 um 06:38 Uhr)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#2

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 15. Okt 2013, 08:48
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:
public interface IPlugin
{
  string GetName();
  string GetDescription();
  string GetVersion();
  UserControl ConfigurationDialog();
  void Execute();
  ...
}
2. Der Plugin-Loader im Hauptprogramm. Sucht nach Assemblies und importiert die, die IPlugin implementieren.
Code:
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();
      ...          
   }
}
Der Plugin-Wrapper:
Code:
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));
  }
}
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.

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.
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.987 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 15. Okt 2013, 11:33
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
  Mit Zitat antworten Zitat
Elvis

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

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 15. Okt 2013, 19:07
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.
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
Furtbichler
(Gast)

n/a Beiträge
 
#5

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 15. Okt 2013, 19:55
Es wäre jedenfalls wichtig, dass man auch mehrere Plugins parallel laden und nutzen kann.
Natürlich.
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.987 Beiträge
 
Turbo Delphi für Win32
 
#6

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 16. Okt 2013, 06:55
Hassu einmal Build Solution [F6] ausgeführt?
Ja, habe ich gemacht. Ich habe jede Klassenbibliothek etc. auch mal manuell kompiliert und die DLLs wurden angelegt.
  Mit Zitat antworten Zitat
Elvis

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

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 16. Okt 2013, 12:48
Hassu einmal Build Solution [F6] ausgeführt?
Ja, habe ich gemacht. Ich habe jede Klassenbibliothek etc. auch mal manuell kompiliert und die DLLs wurden angelegt.
Hast du die Dateien vllt im Netzwerk liegen? .Net ist zwar mittlerweile weniger zickig was das Intranet angeht, aber immer noch zickig genug um ab & zu zu nerven.

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:
msbuild MefSimpleDemo.sln /t:Rebuild /p:Configuration=Debug
oder die Ausgabepfade in den beiden Projekten anpassen.
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
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.987 Beiträge
 
Turbo Delphi für Win32
 
#8

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 16. Okt 2013, 15:25
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.
Jupp. Puh das ist dann aber umständlich. Aber ich kann's versuchen ...
Ich kann mit C# Express schon ein Release-Build generieren, aber der wird nicht als gültige DLL akzeptiert, wie's aussieht.
  Mit Zitat antworten Zitat
Elvis

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

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 16. Okt 2013, 22:41
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.
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
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.987 Beiträge
 
Turbo Delphi für Win32
 
#10

AW: MEF: Plugin-Schlittstelle in C#/WPF

  Alt 17. Okt 2013, 06:48
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.
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.
Da wäre eine Warnung des Debuggers o.ä. eigentlich angebracht ...

Nochmals vielen Dank euch beiden!

Geändert von Matze (17. Okt 2013 um 07:40 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 +2. Es ist jetzt 06:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf