wtorek, 21 lutego 2012

Rozszerzanie aplikacji .NET (czyli plugin'y, add-in'y, MAF, MEF, itp. ...) [PL]


Zostałem ostatnio zapytany jak można zaimplementować aplikację, bazującej na .NET, która miałaby być rozszerzana za pomocą wtyczek (czasem nazywanych też: Add-In, Add-On, Rozszerzenie, Extension, Plug-In, Snap-In, ...), z których każda uruchamiana by była w bezpiecznym środowisku (np. odrębnej domenie aplikacyjnej). Przyjrzyjmy się więc jakie są możliwości tworzenia rozszerzeń dla aplikacji (.NET) i jak można przy ich pomocy zapewnić wspomniane bezpieczeństwo.

Sposób „wszystko zrobię sam (może uda mi się wynaleźć koło na nowo)” :-)

Oczywiście do zaimplementowania mechanizmu wtyczek wystarczą nam podstawowe mechanizmy dostępne w .NET. Tworzymy menedżer wtyczek, który ładuje plik assembly zawierający wtyczkę (najczęściej plik dll), wytwarzamy obiekt odpowiedzialny za funkcjonowanie wtyczki i ... niby już. O tym sposobie pisałem już wcześniej we wpisie: „Jak zaimplementować mechanizm wtyczek (plugin'ów) w .NET”. Oczywiście ten prosty przykład trzeba rozszerzyć, o kwestię dodatkowego bezpieczeństwa poprzez ładowanie wtyczki do osobnej domeny aplikacyjnej lub piaskownicy (sandbox): „Bezpieczne wykorzystanie obcych assembly (C# .NET 2.0 – 3.5)” (niestety wspomniany artykuł dotyczy tylko .NET 2.0-3.5, dla .NET 4.0 potrzebne jest trochę inne podejście).
Opisany tutaj sposób („wszystko zrobię sam”), a raczej wspomniane przykłady, mają jednak pewne wady: niemal pominąłem w nich obsługę błędów, wyszukiwanie wtyczek (nazywane też odkrywanie, discovery) jest bardzo ubogie, brak identyfikacji i zarządzania wtyczek, nie ma wyładowania (unload) wtyczek, na pewno będą problemu z kompatybilnością (po zmianie interfejsu w przyszłości) i pewnie można by wymienić jeszcze kilka podobnych niedoróbek. To chyba świadczy o tym, że może lepiej wykorzystać coś bardziej gotowego.

Managed Extensibility Framework (MEF)

Przyjrzymy się MEF-owi, ten framework (lub jeśli komuś bardzo zależy na polskim odpowiedniku „zrąb” :-) ), został opracowany właśnie, by pomóc w tworzeniu rozszerzalnych aplikacji. MEF używa DI/IoC jako strategii pozwalającej na komponowanie różnych rozszerzeń, chociaż nie jest typowym generycznym kontenerem DI /IoC. MEF zapewnia standardową obsługę hosta aplikacji, by ta wyeksponowała się (jak rozszerzenie), jak i skonsumowała zewnętrzne rozszerzenia. Rozszerzenia mogą być używane również w innych aplikacjach, jednakże muszą być zaimplementowane w sposób dedykowany tylko dla tej aplikacji. Rozszerzenia mogą zależeć od siebie nawzajem i to MEF pilnuje właściwego wiązania (i w odpowiedniej kolejności). MEF oferuje mechanizmy odkrywania i lokalizowania elementów oraz ładowania rozszerzeń. MEF pozwala na oznaczanie rozszerzeń pewnymi metadanymi, które później można odczytywać, odpytywać, czy filtrować.
Niestety nie powstał na tym blogu jeszcze żaden artykuł poświęcony MEF, można jednak obejrzeć moją prezentację na ten temat (wpis: „»Wprowadzenie do MEF w .NET 4.0« - Prezentacja i kod ze spotkania Łódzkiej Grupy .NET”) oraz można ściągnąć przykładowy kod źródłowy: : https://docs.google.com/leaf?id=0B6FppOWQFLIbNjE2NDExOWQtYzRlNC00ZjY2LTlmMDYtM2NjNzYxY2Y2ODdi&sort=name&layout=list&num=50. Inne wartościowe materiały można znaleźć tutaj:
Ja ze swojej strony mogę dodać, że z MEF korzysta się prosto i wygodnie. Jest jednak jedno „ale”: MEF skupia się bardziej na kompozycji, a mniej na samych wtyczkach (add-in, plug-in). Niestety w MEF nie znajdziemy rozwiązania problemu z kompatybilnością wtyczek oraz (co gorsze) nie ma zabezpieczeń w postaci ładowania rozszerzeń do osobnych domen aplikacyjnych, czy piaskownic. Oczywiście wspomniane wady można rozwiązać przy pomocy pewnych dodatkowych elementów (ale czasami chciałoby się mieć wszystko w jednym miejscu :) ).

Managed Add-in Framework (MAF lub po prostu: System.Addin)

W tym kolejnym „zrębie” ( :-) ) kolejne Microsoftowe podejście do mechanizmu wtyczek (tu przede wszystkim nazywanych: „add-in”). Istniej ono już wewnątrz .NET framework od wersji .NET 3.5 (w odróżnieniu od MEF, który został dodany w .NET 4.0). Wykorzystanie MAF jest na pierwszy rzut oka dość skomplikowane, jednak tak pozorna komplikacja daje naprawdę duże możliwości. W MAF położono duży nacisk na separację pomiędzy aplikacją gospodarza (host) a wtyczką (add-in), dlatego pomiędzy znalazły się takie elementy jak:
  • Host view o add-ins – czyli interfejsy, przez które aplikacja widzi swoje rozszerzenia,
  • Host side adapters – czyli adaptery dostosowujące wspomniane interfejsy widoki do aktualnego kontraktu)
  • Contracts – czyli interfejs (kontrakt) , na którym oparta jest współpraca,
  • Add-in side adapters – czyli adaptery dostosowujące wspomniany kontrakt do widoku od strony wtyczki.
  • Add-in view – konkretne interfejsy, na których oparte są wtyczki.
Przedstawione zostało to na poniższym schemacie (żródło MSDN):
W szczególności zaimplementowane rozwiązania pozwalają na zapewnienie kompatybilności pomiędzy aplikacja gospodarza a rozszerzeniami oraz zapewniono możliwość uruchamiania wtyczek w środowisku izolowanych (łącznie z odrębnymi plikami konfiguracyjnymi, czy innymi plikami dll hosta).
Na moim blogu nie pisałem do tej pory nic na temat MAF (chociaż mam plany), teraz polecam zapoznanie się z:
Warto tutaj jeszcze dodać, że jest możliwe połączenie MAF z MEF i uzyskanie na prawdę „wszechmocnego” rozwiązania.
Mam nadzieję, że udało mi się przybliżyć podstawowe możliwości jakie mają programiści .NET, tworzący rozszerzalne aplikacje. A może korzystacie jeszcze z innych rozwiązań? Zapraszam do dyskusji w komentarzach.
Promuj

Brak komentarzy:

Prześlij komentarz

Posty powiązane / Related posts