Entwickler-Ecke

Open Source Units - DphMEF


delfiphan - Sa 31.07.10 13:18
Titel: DphMEF
DphMEF
Einleitung
In der .NET Welt gibt es das MEF (Managed Extensibility Framework), womit man relativ einfach Plugins schreiben kann, aber auch generell für Dependency Injection u.ä. brauchen kann.

Ich habe heute morgen mal ein Mini-MEF für Delphi gebaut. Ist von der Qualität her jetzt eher wie eine Feasibility, kein Productioncode, aber fürs erste schon mal ganz okay.

Bei Delphi mag der Plugingedanke weniger Sinn machen, da man keine Klassen zur Laufzeit nachladen kann. Trotzdem kann man DphMEF ganz gut gebrauchen, um Teile der Applikation vom Framework zusammenbauen zu lassen.

Erfordert Delphi 2010 wegen den Attributen.

Was macht DphMEF?
Einfach gesprochen sucht sich DphMEF Klassen, die mit dem Attribut [Export] versehen sind und injected es in Properties oder Konstruktoren anderer Klassen, die mit dem Attribut [Import] versehen sind. So fügt es die verschiedenen Teile einer Applikation zusammen und macht das Handhaben von komplizierten Abhängigkeiten einfacher.

Wie wird DphMEF verwendet?
Wenn man Beispielsweise einen Logger braucht, muss man lediglich ein Property für den Logger machen, mit einem [Import] Attribut bzw. ein Konstruktor mit dem [ImportingConstructor] Attribut, und kriegt so einen Logger injected. Der Logger muss entsprechend mit [Export] gekennzeichnet worden sein. DphMEF arbeitet konfigurationsfrei. Es ist sogar so, dass man Klassen nirgends (!) im Code referenziert, und trotzdem brauchen kann... Damit der Delphi-Compiler die Klassen überhaupt reinkompiliert und nicht gleich weglässt muss man jedoch noch etwas beachten (mehr dazu später).

Welche Attribute werden unterstützt?
[Export]: Exportiert eine Klasse
[Import]: Importiert ein einzelnes Objekt
[ImportMany]: Importiert als Array
[InheritedExport]: Markiert ein Interface oder eine Basisklasse, sodass alle Implementierungen oder abgeleiteten Klassen automatisch exportiert sind
[PartCreationPolicy]: Definiert, ob ein Objekt jedesmal neu erzeugt werden soll oder recycled werden kann
[ImportingConstructor]: Markiert ein Konstruktor für Konstruktor-Injection
[ExportMetaData]: Basisklasse für meta Daten bei Lazy Evaluierung

Demo
Die Demo enthält Beispiele für alle Attribute. Es zeigt eine modulare Applikation mit einfachen Abhängigkeiten. Es gibt im Projekt keine Unit, die andere Units ausser den beiden Units Infrastructure.pas und DphMEF.pas referenzieren. Die Unabhängigkeit geht so weit, dass man die Framedatei einfach löschen kann, wenn man es nicht sehen will.

Screenshot

Schlusswort
Das ganze ist keine Übersetzung von MEF in .NET sondern versucht die wichtigsten Features wiederzugeben. Das Feature-Set in .NET ist natürlich viel grösser und der Code hier ist wie gesagt eher eine Feasbility als für den täglichen Gebrauch.


delfiphan - Mo 02.08.10 21:44

Neue Version: Mit Lazy Evaluation und Metadaten Support.

Beispiel: Will eine Klasse alle IExample Exports, kann sie diese so erhalten:

Delphi-Quelltext
1:
2:
  [ImportMany]
  property Examples: TArray<ILazy<IExample>> read FExamples write FExamples;

Die "Example"-Property erhält dann alle relevanten Exports, ohne diese zu instanzieren.

Die Klasse kann zuerst über Examples[I].MetaData nachschauen, ob ein einzelner Import tatsächlich interessant ist. Erst bei der ersten Ausführung von Examples[I].Value wird das Objekt dann tatsächlich instanziert. Ist auch bei Constructor-Injection interessant, um zirkuläre Abhängigkeiten zu umgehen.

Die neue Demo oben zeigt alle Features von DphMEF. Es zeigt, wie man eine modulare Applikation einfach und mit ganz wenigen Abhängigkeiten schreiben kann! :)