2009-06-01 6 views
3

Ich arbeite an einer Anwendung, die Plugins beim Start von einem Unterverzeichnis lädt, und derzeit mache ich dies mithilfe von Reflektion, um über die Typen jeder Assembly zu iterieren und öffentliche Klassen zu finden, die das IPluginModule implementieren Schnittstelle.Reflection vs. Attribute in Plugin-Architektur

Da Reflection einen Leistungseinbruch beinhaltet, und ich erwarte, dass es nach einiger Zeit mehrere Plugins geben wird, habe ich mich gefragt, ob es sinnvoll wäre, ein benutzerdefiniertes Attribut auf Assemblyebene zu definieren, das überprüft werden kann Typen (möglicherweise etwa ein Dutzend Typen in einer Assembly, einschließlich 1 Implementierer von IPluginModule). Das Attribut, falls vorhanden, könnte dann eine Methode bereitstellen, um die benötigten Typen oder Instanzen zurückzugeben, und das Iterieren über die Typen wäre dann nur ein Fallback-Mechanismus.

Das Speichern der Typinformationen in einer Konfigurationsdatei ist keine Option.

Würde dies die Leistung verbessern, oder spielt es keine Rolle, wie viel Zeit tatsächlich benötigt wird, um die Baugruppe aus dem Speicher zu laden? Würde diese Verwendung überhaupt für ein Attribut geeignet sein?

+0

Leistungshit? Ich würde das von Java erwarten, aber nicht von C# - ich würde gerne wissen, ob und wie du das gemessen hast. –

Antwort

7

Ich werde Ihre Frage mit einer Frage beantworten: Warum machen Sie sich Sorgen darüber?

Sie sich Gedanken über eine Potential Leistungseinbußen in einem einmal Betrieb, weil es mehrere Plugins zu einem späteren Zeitpunkt sein könnte.

Wenn Ihre Anwendungsstartzeit für einen Benutzer nicht zu lang ist, würde ich keine Zeit damit verschwenden, darüber nachzudenken - es gibt wahrscheinlich viel bessere Dinge, an denen Sie arbeiten können, um Ihre Anwendung zu verbessern.

+0

Ich versuchte zuerst den Konfigurationsvorschlag, aber dann fand ich heraus, dass es fast keinen Unterschied macht, da ich Activator/Assembly.CreateInstance sowieso verwenden musste. Jetzt verwende ich ein benutzerdefiniertes Assembly-Level-Attribut, um die Typnamen zu erhalten, und wie Sie schon erraten haben, habe ich bereits andere Bereiche gefunden, in denen ich die Startzeit verbessern kann. – Botz3000

+0

Ja, mit der Konfiguration würde man einfach das Looping verpassen und überprüfen, ob eine Klasse Ihre Schnittstelle implementiert hat ... Sie würden einfach wissen, welche das getan hat. – CSharpAtl

+0

Das Laden und Abrufen einer Liste aller Arten von Baugruppen kann ein Leistungs- und Speicherproblem sein. Indem Sie alle Typen abrufen, laden Sie eine große Menge an Typ-Infrastruktur in den Arbeitsspeicher, die die CLR normalerweise laden würde. Das ist etwas zu berücksichtigen. –

0

Ich hätte gedacht, dass das Abfragen einer Assembly für alle Klassen, die mit einem Attribut versehen sind, auch Reflektion verwenden würde. Es käme dann auf die Metadaten, die Schnittstellenimplementierung oder die Attributmarkierung zurück?

+0

Ich glaube, ich habe irgendwo gelesen, dass das Durchsehen der Metadaten schneller ist. Aber wir reden wirklich nur über Millisekunden, da bin ich mir sicher. – IAbstract

7

Sie könnten auch die Plug-in-Typen in einer Konfiguration haben, so dass Sie die genauen Klassen kennen, statt alle Klassen durchlaufen zu müssen. Müsste ein Konfigurationsprogramm für diese Option haben ... könnte aber je nach der Anzahl der Klassen, die Sie durchlaufen, eine gute Leistungssteigerung erzielen.

+0

+1 - genau so mache ich es. Registrieren Sie die Plugins mit der Anwendung in der Konfiguration. Ich benutze dann einen benutzerdefinierten Abschnitt Handler, um die Plugins tatsächlich zu laden. – tvanfosson

+0

Ich auch nur durchlaufen eine Assembly, wenn es zuerst hinzugefügt wird. Ich extrahiere die Details, die ich für später brauche (plus einige benutzerfreundliche Informationen). Diese Daten werden für die spätere Verwendung (über Activator) serialisiert. Der Benutzer hat auch die Möglichkeit, Plug-Ins beim Start automatisch zu installieren. – IAbstract

3

Ich glaube, dass beide von Microsoft.net Plugin-Frameworks, das Managed AddIn Framework (MAF) und das Managed Extensibility Framework (MEF) entweder Attribute oder Reflektion verwenden können, um Plugins zu entdecken. Microsoft scheint also zu glauben, dass Attribute angemessen sind.

Ich bin nicht sicher, was die Leistungsunterschiede sind, obwohl.

1

Eine gute Lösung ist, alle Informationen über Plugins zwischenzuspeichern. Wenn die Anwendung zum ersten Mal gestartet wird, führt sie einen vollständigen Scan der DLLs des Plugins durch und speichert die Liste der in einer Datei gefundenen Typen. Beim nächsten Start der Anwendung werden die Informationen aus der Datei geladen, was viel schneller ist als das erneute Scannen aller DLLs. Die Anwendung kann auch einen Zeitstempel für jede DLL speichern. Wenn sie also eine Änderung in einer DLL feststellt, kann sie sie erneut scannen und den Cache aktualisieren.

Das ist im Grunde der Ansatz der Mono.Addins framework folgte.

+0

Danke, gute Idee. – Botz3000