Pluginfähige Anwendung

  • C#

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von nikeee13.

    Pluginfähige Anwendung

    Moin,

    Ich hab versucht das PluginSystem von Mikeb in C# umzubauen, folgendermaßen sieht es aus;


    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Windows.Forms;
    6. namespace Circum
    7. {
    8. public class PlugInConnector
    9. {
    10. public static IPlugin LoadPlugIn(string strFile)
    11. {
    12. IPlugin vPlugIn = default(IPlugin);
    13. System.Reflection.Assembly a = System.Reflection.Assembly.LoadFile(strFile);
    14. Type[] types = a.GetTypes();
    15. foreach (Type pType in types)
    16. {
    17. //hier wird versucht die dll zu laden.
    18. //dies funktioniert nur, wenn die dll auch das selbe interface implementiert
    19. //wie der host vorgiebt
    20. try
    21. {
    22. vPlugIn = (IPlugin)a.CreateInstance(pType.FullName);
    23. //dll ist ein gültiges plugin
    24. return vPlugIn;
    25. }
    26. catch(Exception ex)
    27. {
    28. MessageBox.Show(ex.Message);
    29. }
    30. }
    31. //keine gültige dll gefunden
    32. return null;
    33. }
    34. }
    35. }

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. namespace Circum
    6. {
    7. public interface IPlugin
    8. {
    9. string PluginName { get; }
    10. string PluginAutor { get; }
    11. string PluginDescription { get; }
    12. string PluginHostString { get; }
    13. string PluginVersion { get; }
    14. }
    15. }

    C#-Quellcode

    1. foreach(string plugin in Directory.GetFiles(Application.StartupPath + @"\Plugin\"))
    2. {
    3. PluginList.Add(PlugInConnector.LoadPlugIn(plugin));
    4. }
    5. MessageBox.Show(PluginList[0].PluginName); //Einfacher Test


    Plugin: (Hat auch IPlugin)

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. namespace Circum
    6. {
    7. public class YouTube : IPlugin
    8. {
    9. public string PluginName { get { return "YouTube"; } }
    10. public string PluginAutor { get { return "Circum-Team"; } }
    11. public string PluginDescription { get { return "Implements Host:YouTube"; } }
    12. public string PluginHostString { get { return "youtube"; } }
    13. public string PluginVersion { get { return "1.1"; } }
    14. public YouTube()
    15. {
    16. }
    17. }
    18. }


    Leider bekomme ich beim Laden immer die Fehlermeldung;

    Der Konstruktor für Circum.IPlugin wurde nicht gefunden
    Das Objekt Circum.YouTube kann nicht in Circum.IPlugin umgewandelt werden.



    Was habe ich falsch gemacht?

    Danke

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nikeee13“ ()

    Quellcode

    1. foreach (Type type in types)
    2. {
    3. if (typeof(IPlugin).IsAssignableFrom(type))
    4. {
    5. //hier wird versucht die dll zu laden.
    6. //dies funktioniert nur, wenn die dll auch das selbe interface implementiert
    7. //wie der host vorgiebt
    8. try
    9. {
    10. vPlugIn = (IPlugin)a.CreateInstance(pType.FullName);
    11. //dll ist ein gültiges plugin
    12. return vPlugIn;
    13. }
    14. catch(Exception ex)
    15. {
    16. MessageBox.Show(ex.Message);
    17. }
    18. }
    19. }
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.
    Autorinformationen würde ich in ein CustomAttribute packen, da du dann keine Instanz der Plugin-Klasse brauchst, um diese Infos auszulesen.

    Außerdem gibt es in .NET bessere Methoden, ein Pluginsystem aufzubauen. Ich bevorzuge MEF.
    Ein einfaches Plugin-System mit verschiedenen Plugin-Quellen lässt sich einfach in ein paar Zeilen realisieren:
    just-about.net/mef-tutorial

    stackoverflow.com/questions/20…ere-can-i-learn-about-mef

    Übrigens kann eine DLL auch mehrere öffentliche IPlugin-Implementierungen haben - das bleibt bei deiner Lösung vollkommen raus.
    Bei MEF benötigst du nur ein ImportMany-Attribut vor z.B. einer List<IPlugin>. Dann noch die Plugins laden und alles funktioniert automatisch. ;)
    Von meinem iPhone gesendet
    @Chrisber²: Es kommt zumindest keine Fehlermeldung mehr, aber das abrufen der Property in der Messagebox bleibt trotzdem aus, es wird null zurückgegeben.

    Ich kenn mich mit sowas garnicht aus, deswegen verzeih mir ;)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ThuCommix“ ()

    Was machst du es dir so schwer?
    Hättest nur den ersten Artikel überfliegen müssen, den ich gepostet habe. Mit dem MEF dauert das 2 Minuten.

    Man hat .NET 3.5/4 nicht umsonst. Da gibt es sowas schon vom Framework aus. Wenn man unter .NET 3.5 arbeitet, kann man sich MEF von Codeplex ziehen.
    Eure Methoden sind etwas "veraltet". ;)

    In der Klasse, in der die Plugins sein sollen:

    C#-Quellcode

    1. [ImportMany(typeof(IPlugin))] //Festlegen, dass dieses Feld mit importierten IPlugin-Instanzen gefüllt werden soll
    2. private IPlugin[] _plugins = null;
    3. public void LoadPlugins()
    4. {
    5. var catalog = new DirectoryCatalog("./Plugins/"); //Eine Import-Quelle angeben (gibt noch andere)
    6. var container = new CompositionContainer(catalog); // Quelle zum Container hinzufügen
    7. container.ComposeParts(this); //Alle Imports aus den Exports hereinladen (hier werden die Plugins geladen)
    8. #if DEBUG
    9. foreach (IPlugin contract in _plugins)
    10. { //Zu testzwecken mal alles ausgeben.
    11. Debug.WriteLine("Plugin von Autor geladen: ");
    12. Debug.WriteLine(contract.AuthorName);
    13. }
    14. #endif
    15. }
    (Das ersetzt also die komplette PluginConnector-Klasse und das Teil, das die Methode aufruft)

    Klassen, die Plugins sein sollen, müssen dann IPlugin implementieren und mit dem Attribut gekennzeichnet sein:

    C#-Quellcode

    1. [Export(typeof(Circum.IPlugin))] //Festlegen, dass diese Klasse exportiert werden kann


    Es werden dann alle IPlugin-Teile geladen, die sich in den Assemblies im Unterordner Plugins befinden. Von jedem Plugin landet dann eine Instanz im Array _plugins. Das Array kannst du natürlich auch durch eine List<T> ersetzen.

    Die Namespaces kannst du dir über die Auflösen-Funktion holen.

    Fertig.

    Edit:
    Tutorial hier:
    vb-paradise.de/allgemeines/tip…utorials/allgemein/87231-
    Von meinem iPhone gesendet

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „nikeee13“ ()

    Danke danke danke! Versteh mich nicht falsch, ich habe bereits das hier abgearbeitet: mef.codeplex.com/wikipage?titl…iner&referringTitle=Guide

    Ich wollte nur trotzdem wissen wieso das erstere nicht funktioniert hat ;)

    Funktioniert :>
    Bilder
    • Unbenannt.png

      32,82 kB, 451×322, 182 mal angesehen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ThuCommix“ ()

    Mist doch noch eine Frage, gibt es eine Möglichkeit Plugins zu unloaden? Wie ich bis jetzt gelesen habe, ist das eigentlich in MEF nicht vorgesehen, brauche es aber dringend um z.B Plugins zu aktualisieren oder zu Entfernen.