Veel applicaties beginnen klein, maar groeien in de loop van de tijd uit tot grote en complexe systemen. Wanneer die systemen niet uit heldere bouwstenen ontstaan, kom je al snel in een situatie waar een kleine wijziging op één gebied een cascade aan problemen op andere plekken in de software kan veroorzaken.
Door applicaties modulair op te bouwen wordt je gedwongen om in kleine bouwstenen te denken. MEF geeft daar bovenop de mogelijkheid om deze bouwstenen dynamisch in je systeem te laden.
Hoe functioneert MEF
MEF bestaat uit drie belangrijke onderdelen:
– Export van metadata
– Import van objecten op basis van metadata
– Een catalogus en container om geëxporteerde objecten te beheren en te mappen op te importeren dependencies.
Objecten exporteren
Om objecten beschikbaar te maken voor MEF, kun je gebruik maken van de export functionaliteit.
In de basis geeft deze export je de mogelijkheid om een type te definiëren en er desgewenst een contract naam aan te geven (string). De metadata die je definieert bij het exporteren wordt gebruikt bij het importeren om de juiste objecten op te zoeken. Wanneer je extra metadata wilt definiëren kun je ook eigen implementaties van het export attribuut maken.
Vervolgens kun je deze eigen methode gebruiken om je plugins van de juiste metadata te voorzien.
Wanneer je specifieke eisen hebt, m.b.t. de wijze waarop MEF instanties aanmaakt kun je dit opgeven bij de export.
Objecten importeren
MEF heeft in zijn manier van werken veel overeenkomsten met IOC-frameworks. Onder andere dat bij het resolven van een dependency-tree niet alleen het opgevraagde object, maar ook de lager gelegen afhankelijkheden geresolved worden. De standaard imports kunnen hierbij geplaatst worden op fields en de constructor.
Deze beide methodieken werken prima voor lagergelegen afhankelijkheden, maar op het hoogste niveau is vaak een collectie van plugin objecten nodig.
Om een collectie van plugins via MEF in te kunnen laden, definieer je een import many. Om te voorkomen dat alle gevonden objecten pas geïnstantieerd worden wanneer ze worden aangeroepen kun je gebruik maken van een lazy collectie.
Een catalogus definiëren
Om geëxporteerde objecten te kunnen gebruiken moet je een catalogus samenstellen. Sommige frameworks (bijvoorbeeld caliburn micro) gebruiken MEF voor inversion of control. In dat geval zullen meestal de verschillende assemblies niet als plugins, maar als reference worden gecatalogiseerd.
Wanneer je plugins wilt gebruiken kun je gebruik maken van een directory catalog.
Om vervolgens een object door MEF te laten opbouwen gebruik je de compose methode.
In het voorbeeld van de plugin collection zal de compose parts opdracht ervoor zorgen dat de lazy collection gevuld wordt met de juiste afhankelijkheden.
Auteur: Menno Jongerius, Bergler Competence Center 2016