piątek, 2 marca 2012

[MAF 01] Rzut okiem na Managed Add-in Framework (System.AddIn) [PL]

Nie dawno (patrz wpis: „Rozszerzanie aplikacji .NET (czyli plugin'y, add-in'y, MAF, MEF, itp. ...)”) wspomniałem na tym blogu o Managed Aadd-in Framework (zwanego również System.AddIn lub MAF), przyjrzyjmy się bliżej temu rozwiązaniu.

Naszą przygodę z MAF zacznijmy może od powrotu to pokazanego wcześniej rysunku, który zaczerpnięty został z MSDN:
Muszę przyznać, że musiałem się chwilę zastanowić, gdy go pierwszy raz zobaczyłem. Przedstawia on tzw. pipeline, czyli ścieżkę prowadzącą przez poszczególne segmenty pomiędzy aplikacją gospodarza (host'a) a wtyczką (add-in'em). Wspomniana ścieżka jest właśnie wykorzystywana do komunikacji pomiędzy aplikacją a jej wtyczką. Dlaczego zostało jednak to tak skomplikowane?
Aby odpowiedzieć sobie na postawione pytanie zacznijmy może od najprostszego przypadku (nie związanego z MAF!). Aplikacja (nazwijmy ją Host) zawiera pewne komponenty (nie wtyczki, a raczej obiekty klas współtworzących aplikację). W takim przypadku wspomniane komponenty związane są bezpośrednio z aplikacją. Nie jest to dobre rozwiązanie i każdy mający pewną wprawę w tworzeniu oprogramowania wolałby taką zależność usunąć. Jak to zrobić? Najprościej można to rozwiązać dodając pomiędzy wspomnianego Hosta a Komponent dodatkowe elementy, które można nazwać kontraktem. Taki kontrakt najczęściej ma postać klas abstrakcyjnych lub interfejsów. Rozwiązanie to można przedstawić na rysunku:
Jest to również najbardziej klasyczne podejście do rozwiązania problemu z wtyczkami. Przykład takiego rozwiązania przedstawiłem już kiedyś we wpisie: „Jak zaimplementować mechanizm wtyczek (plugin'ów) w .NET (C#)”. W MAF dodano jedna dodatkowy stopień komplikacji....
Wspomniane podejście (Host -> Kontrakt <- Komponent) ma pewną znaczącą wadę, obydwa końce układanki są silnie zależne od kontraktu i przez to wrażliwe na każdą jego zmianę. Jak ten problem rozwiązać? Można wcisnąć pomiędzy wszystkie elementy, jeszcze inne dodatkowe:
Dzięki temu ani Host, ani wtyczka (Add-in) nie są już zależne od kontraktu (Contract), a wyłącznie zależą od swoich widoków/spojrzeń na ten kontrakt (Host views of add-ins, Add-in views) Wspomniane widoki/spojrzenia, to nadal klasy abstrakcyjne lub interfejsy. Zwróćmy też uwagę, że dodane zostały dodatkowe elementy dokonujące adaptacji pomiędzy widokiem, a kontraktem (Host-side adapters, Add-inns-side adapters).
Właśnie taki zabieg dokonano w MAF i powstał wspomniany pipeline:
Rysunek z MSDN-u nie okazuje się więc zupełnie dziwaczny, ale pewnie ktoś mógłby zapytać: „Czy muszę to wszystko wiedzieć?” lub „Czy w moim prostym rozwiązaniu nie mogę jakiś elementów pominąć?”. Otóż okazuje się, że trzeba to wiedzieć i pominąć nie można. Ostatecznie można pewne rzeczy połączyć, ale takie połączenie może okazać się nie do końca sensowne. Jest to związane z faktem, że MAF wymaga odpowiedniej struktury katalogów, w której znajdą się poszczególne kawałki powyższej układanki:
Zauważmy tutaj, że część katalogów jest wymagana (HostSideAdapters, Contracts, AddInSideAdapters, AddInViews, AddIns). W części z nich podkatalogi nie są dozwolone (HostSideAdapters, Contracts, AddInSideAdapters, AddInViews). Natomiast w katalogu AddIns wymagane są katalogi dla każdej wtyczki. Tym co są przerażeni wspomnianymi ograniczeniami zostawiono niewielką dowolność. Mianowicie dodatkowe wtyczki można umieścić w innym katalogu (wskazanym podczas wyszukiwania rozszerzeń przez aplikację: FindAddIns). Dowolna jest również lokalizacja całego pipeline'u (na rysunku Pipeline root), ważne by miała wewnątrz odpowiednią strukturę. Tym którzy nie będą chcieli się podporządkować spotkają kary w postaci wyjątków, ostrzeżeń lub braku działania wtyczki, np.:
  • The assembly "C:\(…)\AddIns\DoSthV1SampleString\MAFSAmple1.Plugin.View.dll" should not be in location "C:\(…) :\(…)\AddIns\DoSthV1SampleString\". Remove it to avoid loader context problems.
  • AddInSegmentDirectoryNotFoundException: The required folder "(...)\AddInSideAdapters" does not exist.
  • Itp...
Na koniec do tak stworzonej struktury katalogów wystarczy powrzucać odpowiednie assembly, które będą klasy lub interfejsy opatrzone odpowiednimi atrybutami i połączone odpowiednimi zależnościami zgodnie z rysunkiem:
Promuj

Brak komentarzy:

Prześlij komentarz

Posty powiązane / Related posts