Plugin System in VB/C# realisieren

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    Plugin System in VB/C# realisieren

    Tach!

    Also zuerst mal zu meinem Problem:
    Ich möchte gerne ein Plugin-System erstellen, bei dem ich eine Hauptanwendung habe, die einen Schnittstelle für Plugins erlaubt.

    Wenn ich über diese Schnittstelle ein neues Plugin einbinde, soll das Plugin selbstständig arbeiten.
    Sprich: Nicht wie in diesem Tutorial hier: Wie erstelle ich ein PlugIn System unter VB.NET (Framework 2), dass ich in meiner Hauptanwendung Funktionen aus dem Plugin aufrufe, die ich selber rein programmiere.
    Sondern, dass das Plugin nach dem Registrieren z.B. einen Button auf der MainForm hinzufügt und wenn ich den dann drücke, die entsprechende Funktion im Plugin aufgerufen wird.
    Ich also NICHT schon beim Programmieren der Hauptanwendung wissen muss, WELCHE Funktionalitäten das Plugin mir zur Verfügung stellt.
    Wie es richtige Plugins halt nunmal tun (Bsp: Notepad++: Da kann ich ja auch ein Plugin(DLL) hinzufügen, daraufhin wird ein neuer Eintrag im Menubar oder im DropDown im Menubar hinzugefügt)

    Hab bisher zwar etliche Tutorials gesehen, aber da wird, wie in dem Tut von mikeb96 immer nur die Variante beschriebenm, dass die Anwendung über Reflections und Schnittstellen festgelegte Funktionen aufruft. Ich will es aber so lösen, dass besagtes Plugin ein Steuerelement auf die Mainform packt, einen Eventhandler registiert und dann das Eventhandling selber iwie löst.

    Einer meiner Gedankengänge wäre gewesen, dass ich im Interface, dass das Plugin definiert, in der Init-Methode(oder wie auch immer ich die nenne) eine Referenz auf die Hauptanwendung mitgebe. Sodass ich dann über die Referenz auf die MainForm Control Collection meine Steuerelemente hinzufüge. Doch dann würde ich mir
    1.) Eine Riesen Sicherheitslücke einfangen(Hacker könnte auf MainForm und die Member zugreifen) und
    2.) Denke ich mal, ist das besch...es Design

    Kann mir bitte wer einen Hinweis/Link auf ein Tutorial gebene, dass meine Anforderungen entspricht?

    Lg Radinator

    PS: Evtl werde ich das dann in ein Tutorial hier auf vb-paradise.de umwandeln. Dann hat jeder was davon ;D
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Radinator schrieb:

    Hab bisher zwar etliche Tutorials gesehen, aber da wird, wie in dem Tut von mikeb96 immer nur die Variante beschriebenm, dass die Anwendung über Reflections und Schnittstellen festgelegte Funktionen aufruft.
    Hängt damit zusammen, dass es AFAIK anders nicht geht (auch nicht in MEF).

    Radinator schrieb:

    Ich will es aber so lösen, dass besagtes Plugin ein Steuerelement auf die Mainform packt, einen Eventhandler registiert und dann das Eventhandling selber iwie löst.
    Jo - designe halt die Schnittstellen dementsprechend.

    Aber denke die Architektur besser richtigrum: Nicht das PlugIn macht was mit der Hauptanwendung, sondern die Hauptanwendung macht was mit dem Plugin.
    Und da kann sie durchaus machen, dass sie vom PlugIn Informationen abruft, wie Buttons zu generieren sind und Eventhandler zu abonnieren.

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

    Naja daas mit dem dass die hauptamwendung was mit dem plugin macht...ich weiß ned...das plugin soll ja die anwendung erweitern.
    bzw das mit dem richtig designen der schnittstelle versteh ich ned...
    oder anders gefragt: soll ich wie bereits im startpost erwähnt in der init funktion eine referenz auf die mainformoder die mainform controll collection geben, damit dias plugin seine controls draufpacken kann oder soll ich das iwie anders lösen?
    weil wen ja, dann kann ich mir schon vorstellen, wie ich das machen...einfach inder init methode das controll adden und danach das event auf das control mit einer, im plugin definierten methode, behandeln

    lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell

    Radinator schrieb:

    das mit dem richtig designen der schnittstelle versteh ich ned...
    Du kannst mit Deiner Anwendung kein Notepad++-AddOn verwenden, weil Du das Interface nicht kennst.
    Du kannst nur solche AddOns verwenden, die ein von Dir unterstütztes Interface verwenden.
    Wenn Du merkst, dass Deinen Interface eine Funktion fehlt, füge sie dem Interface und allen bereits implementierten Interface-Klassen hinzu.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Beschreibe mit einem möglichst konkreten Beispiel, was Du mit diesem Plugin-System erreichen willst.
    Also was die Hauptanwendung macht und was das Plugin macht.

    Als Beispiel: Die Hauptanwendung wendet verschiedene Filter auf Bilder an. Ein Plugin soll Filter bereitstellen, die die Hauptanwendung verwenden kann.
    Das könnte vom Konzept her so aussehen:

    VB.NET-Quellcode

    1. 'Gemeinsame Bibliothek
    2. Interface IFilter
    3. Function Process(Source As Bitmap) As Bitmap
    4. End Interface
    5. 'Hauptanwendung
    6. Class MainForm 'Als Beispiel
    7. Dim Filters As New List(Of IFilter)
    8. Dim CurrentBitmap As Bitmap = ...
    9. Sub New()
    10. 'Alle Filter laden
    11. For Each Assembly In PluginAssemblies 'Von allen Plugins
    12. For Each Type In Assembly.GetTypes.FilterByIFilter 'Alle Typen die IFilter implementieren
    13. Filters.Add(MakeInstance(Type)) 'Eine Instanz davon erzeugen und in der Liste ablegen.
    14. Next
    15. Next
    16. End Sub
    17. Sub Process(FilterIndex As Integer)
    18. CurrentBitmap = Filters(FilterIndex).Process(CurrentBitmap)
    19. End Sub
    20. End Class
    21. 'In der Plugin-Dll
    22. Class GaussianBlur
    23. Implements IFilter
    24. Function Process(Source As Bitmap) As Bitmap Implements IFilter.Process
    25. '...
    26. End Function
    27. End Class

    Also ganz einfach.

    Wie sieht da Dein konkreter Fall aus?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Hi ROF und niko,
    danke schon mal für euer fixen antworten.

    @RodFromGermany: ich will ja auch kein notepad++ affon hinzufügen, ich hab npp nur al bsp angeführt.

    @Niko Ortner: Ein konkretes Bsp wäre ein Rechner:
    in meiner hauptanwendung hab ich diverse reiter, auf denen ich diverse rechenarten durchführe(normales rechnen +-*/), binäre rechenoperstionen. Nun soll die anwenung die mgl haben, plugins zu registrieren, die noch weiter reiter mit anderen rechenoperstionen anfügt(also neuer reiter, in dem ich bspw dann halt mit hexwertrn rechenen kann oder wo ich mir dann fuunktionen plotten kann.
    Dabei soll wie gesagt die verarbeitung der eingaben nicht von der hauptanwendung übernommen werden, die weißj ja ned, wass alles hinzugefügt wird. Sondern ich will halt dann ein event registriern. Was mir danhalt den druck auf den button "plotten" verarbeitet

    lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Gut, das könnte dann so aussehen:

    VB.NET-Quellcode

    1. 'Gemeinsame Bibliothek
    2. Interface ICalculatorTab
    3. ReadOnly Property TabContent As Control
    4. End Interface
    5. 'Hauptanwendung
    6. Class MainForm 'Als Beispiel
    7. Dim CalculatorTabs As New List(Of ICalculatorTab)
    8. Sub New()
    9. 'Alle Filter laden
    10. For Each Assembly In PluginAssemblies 'Von allen Plugins
    11. For Each Type In Assembly.GetTypes.FilterByICalculatorTab 'Alle Typen die ICalculatorTab implementieren
    12. CalculatorTabs.Add(MakeInstance(Type)) 'Eine Instanz davon erzeugen und in der Liste ablegen.
    13. Next
    14. Next
    15. For Each i In CalculatorTabs
    16. TabControl1.Tabs.Add(i.TabContent) 'So in der Richtung
    17. Next
    18. End Sub
    19. End Class
    20. 'In der Plugin-Dll
    21. Class PlusCalculator
    22. Implements ICalculatorUI
    23. Dim _TabContent As New PlusCalculatorControl
    24. ReadOnly Property TabContent As Control
    25. Get
    26. Return _TabContent
    27. End Get
    28. End Property
    29. End Class
    30. Class PlusCalculatorControl 'Kann man mit dem Designer erstellen.
    31. Inherits UserControl
    32. 'TextBoxen und so weiter.
    33. End Class

    Auch hier ist das Schema wie oben erklärt. Die Hauptanwendung gibt vor, was das Plugin können muss (hier: ein Control bereitstellen, das in einem Tab angezeigt wird). Die Hauptanwendung sagt dann dem Plugin: "Hey, gib mir mal das Control.", und das Plugin gibt das Control zurück. In dem Control kann dann x-beliebiges gemacht werden. Hier grabscht nicht das Plugin in der Form herum und fügt sich selbst in die Tab-Liste hinzu, sondern die Hauptanwendung macht das.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils