Laden...

Wie binde ich das dynamische Laden von Plugins in den Programmablauf ein?

Erstellt von JimStark vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.190 Views
JimStark Themenstarter:in
309 Beiträge seit 2020
vor 3 Jahren
Wie binde ich das dynamische Laden von Plugins in den Programmablauf ein?

Hi,

leider finde ich zum Thema Plugins nicht viel. Zumindest wenn es über eine Funktion aufrufen hinausgehen soll.
Mein Problem ist nicht das Laden der DLLs usw. sondern die Architektur des Programmes.

Mein Ansatz war bisher folgender:

Ich habe ein Interface des Pluginhosts (das stellt mein Hauptprogramm dar). Die Plugins bekommen das PluginHost Objekt übergeben und können sich an Events binden oder später auch darüber auf Datenbank, etc. zugreifen.


    public interface IPluginHost
    {
        event EventHandler ApplicationStarted;

    }

Mein Hauptprogramm erstellt sich dann das Hostobjekt und triggert die Events bei Bedarf bzw. stellt später die Felder zur Verfügung.



    public class PluginHost : IPluginHost
    {
        private List<IPlugin> _plugins = new List<IPlugin>();

        public event EventHandler ApplicationStarted;

        public virtual void OnApplicationStarted(EventArgs e)
        {
            EventHandler handler = ApplicationStarted;
            handler?.Invoke(this, e);
        }


        public PluginHost()
        {
            // Test-Plugin laden:
            _plugins.Add(new TestPlugin.MyPlugin(this));
            

        }
    }

// in der Application_Startup z.B.:
private void Application_Startup(object sender, StartupEventArgs e)
{
            // Plugin Host initalisieren:
            PluginHost pluginHost = new PluginHost();

            // ... Programm lädt ....

            // Execute Plugin ApplicationStarted:
            pluginHost.OnApplicationStarted(e);
 }

Das Plugin sieht dann z.B. so aus:



    public class MyPlugin : IPlugin
    {


        public MyPlugin(IPluginHost host)
        {
            host.ApplicationStarted += Host_ApplicationStarted;
        }

        public string Title => "Test-Plugin";

        private void Host_ApplicationStarted(object sender, EventArgs e)
        {
            Debug.WriteLine("Ich bin auch da!");
        }
    }


Jetzt meine Frage, gibts da soweit bessere Möglichkeiten das umzusetzen?

Wenn ich jetzt z.B. Plugins die Möglichkeit geben will ein MenuItem zu bekommen, habe ich das mal so gesehen:
Das heißt die rufe die Funktionen im Plugin auf und sie können mir ein Item zurückgeben oder eben Null.


    public enum Menu
    {
        MainFile,
        MainExtra,...
    }

    public interface IPluginHost
    {
        event EventHandler ApplicationStarted;
        MenuItem GetMenuItem(Menu place);

    }

Wäre das soweit alles, auch in Bezug auf .NET Core richtig oder habt ihr bessere Beispiele/Ideen?
Da das alles ziemlich tief in den Programmablauf eingebunden wird will ich es natürlich auch richtig machen 😁

16.806 Beiträge seit 2008
vor 3 Jahren

Jetzt meine Frage, gibts da soweit bessere Möglichkeiten das umzusetzen?

Besser ist immer relativ; kommt auf die Anforderungen an, die halt nur Du kennst.
Du hast hier ja nich mal ein Wort verloren, welche Art von Anwendung Du überhaupt hast.

Wäre das soweit alles, auch in Bezug auf .NET Core richtig oder habt ihr bessere Beispiele/Ideen?

Kommt auf die Art der Anwendung und auf die Anforderungen an, die eben - auch hier - nur Du kennst.

will ich es natürlich auch richtig machen 😄

Richtig ist etwas immer nur solange, bis es eine Anforderungsänderung gibt, die was neues erfordert.
Daher such Dir eine Lösung, die einfach ist und die Anforderungen erfüllt.

Macht kein Sinn sofort die Weltbeste Lösung zu programmieren, die man vielleicht niemals braucht.

T
2.219 Beiträge seit 2008
vor 3 Jahren

Die Anforderung ist hier zu spezifisch und auch nur in deinem Anwendungsfall sinnvoll.
Welche Lösung sollte man dir hier anbieten können?
Eine Allgemeine Lösung für Plugins und deren Umsetzung, hängt wie immer von dem konkreten Anwendungsfall ab.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

JimStark Themenstarter:in
309 Beiträge seit 2020
vor 3 Jahren

Okay, danke euch beiden. Dachte es würde evtl. einen eleganteren Weg, Pattern, etc. geben.
Dann werde ich es erstmal so machen.

Eine Frage noch zu diesem Thema. Vielleicht kann man es auch in einen eigenen Thread trennen:

Ich habe ein ViewModel mit den Controls der Plugins. z.B.:



public class PluginsViewModel : BaseViewModel
{
      private List<MenuItem> _ContextMenuItems;
      public List<MenuItem> ContextMenuItems { get { return _ContextMenuItems; }}
...
}


Darin fülle ich dann, falls vorhanden, die von den Plugins zurückgegeben MenuItems.

Jetzt kann ich per XAML ja direkt die Items binden:


<MenuItem Header="Extras" ItemsSource="{Binding MyPluginsViewModel.ContextMenuItems}"/>

Gibt es einen Weg wenn ich per XAML schon Subitems definiert habe diese noch zu Erweitern? Ohne Codebehind und ohne die bereits vorhandenen Items im ViewModel dynamisch hinzuzufügen.


<MenuItem Header="Extras">
   <MenuItem Header="Bla">
   ...
   // Hier die ContextMenuItems hinzufügen
</MenuItem>