Trwa konkurs "Ogól naczelnego", w którym codziennie możecie wygrać najnowsze maszynki systemowe Hydro Connect 5 marki Wilkinson Sword.

Więcej informacji
Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Managed Extensibility Framework — system pluginów do aplikacji .NET od Microsoftu

W poprzednim wpisie pokazałem jak szybko stworzyć własne okienko w Visual Studio (timer w okienku IDE). Dziś opiszę MEF, czyli framework do tworzenia lekkich aplikacji i pisania rozszerzeń do nich. To właśnie na nim opiera się IDE od Microsoftu.

MEF w teorii

Obecnie MEF (Managed Extensibility Framework) jest komponentem .NET 4.0. Biblioteka powstała jako odpowiedź na zapotrzebowania programistów w tworzeniu aplikacji, które mogłyby być rozszerzalne poprzez zewnętrzne pluginy (reużywalne). Jest on zbiorem wcześniejszych doświadczeń, który pozwala w prosty sposób na zaimplementowanie systemu rozszerzeń w każdej aplikacji .NET, bez tworzenia kolejnego frameworku od zera.

MEF można uznać za bibliotekę pozwalająca na Dependency Injection opartą na atrybutach. Pozwala ona na tworzenie aplikacji na zasadzie odkrywania (wyszukiwania) rozszerzeń i ładowania ich dynamicznie do programu. Takie dodatki mogą być reużywalne przez różne aplikacje. MEF umożliwia dla programu, do którego ładowane są wtyczki, stworzenie sposobu na identyfikację i walidację takiego zewnętrznego kodu, a także jego uruchomienie.

Managed Extensibility Framework pozwala zarówno na tworzenie wtyczek, jak i aplikacji, które będę z nich korzystać. Framework umożliwia także rozszerzanie platformy o własne rozwiązania i biblioteki, bazując na MEF. Visual Studio korzysta z MEF i pozwala w ten sposób na pisanie dodatków, powiększających możliwości IDE.

Composition container, catalog, parts

Aplikacje pisane w MEF bazują na podstawowych elementach: kontener z kompoyzcją (composition container), katalog (catalog) i elementy (parts).

  • parts - podstawowa jednostka MEF, która umożliwia import i eksport funkcjonalności poprzez kontrakt; kontrakt (contract) jest sposobem na łączenie poszczególnych części
  • composition container - jest to rdzeń rozwiązań MEF, to tutaj przechowane są dostępne elementy (parts), zarządza się instancjami poszczególnych elementów i w tym miejscu następuje kompozycja (łączenie wymaganych części [imports] z tymi dostępnymi [exports])
  • catalog - jest to abstrakcyjne miejsce, które gromadzi elementy do użycia w kontenerze z kompozycją; MEF udostępnia katalogi, które pozwalają na odkrywanie (discover) elementów (parts) poprzez typy (TypeCatalog), assembly (AssemblyCatalog), foldery (DirecotryCatalog) i inne katalogi (AggregateCatalog)

MEF w praktyce

Zobaczmy zatem jak sprawuje się MEF. W tym celu tworzymy zwykłą aplikację konsolową, którą wykorzysta mechanizm pluginów (pamiętając jednocześnie o dodaniu referencji System.ComponentModel.Composition!).

Aplikacja konsolowa będzie uruchamiała naszego hosta, który to będzie rozszerzony o autorski plugin.

using System; namespace MEFExample { class Program { static void Main(string[] args) { HostApp hostApp = new HostApp(); hostApp.Start(); //just wait to see results Console.ReadKey(); } } }

Stwórzmy zatem prosty interface do pluginu, a także jego implementację.

namespace MEFExample { public interface IMessagePlugin { string GetMessage(); } }

using System.ComponentModel.Composition; namespace MEFExample { [Export(typeof(IMessagePlugin))] public class MessagePlugin : IMessagePlugin { public string GetMessage() { return "Message from plugin"; } } }

W ty miejscu nasza implementacja pluginu jest oznaczona atrybutem Export. Oznacza to tyle, że eksportujemy nasz kod (implementację) do kontenera.

Teraz przyszedł czas na implementację naszego programu hostującego, który będzie rozszerzany przez plugin.

using System; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; namespace MEFExample { public class HostApp { [Import] public IMessagePlugin MessageToClient { get; set; } public void Start() { Compose(); Console.WriteLine(MessageToClient.GetMessage()); } private void Compose() { AssemblyCatalog catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()); CompositionContainer container = new CompositionContainer(catalog); container.ComposeParts(this); } } }

Zauważmy dwa ważne elementy: atrybut Import i metodę Compose. Dodanie atrybutu Import zaimportuje z kontenera implementację IMessagePlugin, która została dodana wcześniej przy eksporcie.

Metoda Compose jest najważniejsza tutaj. W tym miejscu powiadamiamy MEF, iż abstrakcyjny katalog powinien wyszukać elementów (parts) z biblioteki, a tą biblioteką jest aktualnie wykonywane assembly:

AssemblyCatalog catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());

W kolejnym kroku dodajemy powyższy katalog do kontenera z kompozycją:

CompositionContainer container = new CompositionContainer(catalog);

Na koniec łączymy całość i przekazujemy jako parametr instancję, która ma zaimportować elementy z kontenera. W naszym przypadku jest to this, czyli aktualna instancja HostApp, zawierająca proporcję MessageToClient z atrybutem Import.

container.ComposeParts(this);

Po uruchomieniu otrzymamy taki ekran:

MEF i Visual Studio

Po co nam wiedza o MEF? Otóż edytor w Visual Studio został oparty na MEF. Zatem napisanie jakiegokolwiek pluginu do IDE od Microsoftu będzie wymagało dotknięcia do MEF. O czym już konkretniej w kolejnej części.

Źródła dostępne są na GitHubie (branch master i POC):

https://github.com/djfoxer/healthyWithVS/

 

windows porady programowanie

Komentarze

0 nowych
  #1 22.03.2017 19:52

Hejtuje anonimowo za wcześniejszą ucieczkę z CZ ! :D :D :D

molexor   7 #2 22.03.2017 20:07

NO! w końcu coś niecoś o programowaniu! :)
miło widzieć coś na dobrych programach w tej tematyce.
Nie korzystam z mefa- oglądałem sobie to i próbowałem - sympatycznie wygląda, ale do określonych zastosowań. W moim wypadku robiłem głównie apki webowe w webapi wiec dokładanie do nich pluginów byłoby trochę na wyrost. Prościej było użyć wzorca strategia, polecenie, czy cos w tym stylu i wykorzystac IOC, bo oczywiście całość kodu była u mnie pod kontrola ( i teamu ), ale gdyby przyszła konieczność udostępnienia czegoś innym zespołom to Mef to super możliwość

djfoxer   18 #3 27.03.2017 18:45

@hejter-anonimowy (niezalogowany): Musiałem :D

djfoxer   18 #4 27.03.2017 18:46

@molexor: Ciesze się, że wpis przypadł do gustu, zapraszam na kolejne :)

Gratulacje!

znalezione maszynki:

Twój czas:

Ogól Naczelnego!
Znalazłeś(aś) 10 maszynek Wilkinson Sword
oraz ogoliłaś naszego naczelnego!
Przejdź do rankingu
Podpowiedź: Przyciśnij lewy przycisk myszki i poruszaj nią, aby ogolić brodę.