- PVSM.RU - https://www.pvsm.ru -
Посвящается фанатам группы Microsoft Patterns&Practices [1] и просто любителям такой полезной штуки как Microsoft PRISM [2].
Разработчики, которые в своей практике встречались с Microsoft PRISM, вероятно, имеют двоякое мнение об этом фреймворке. С одной стороны, в своей по номеру 4-й, а по порядку 3-й, версии – это очень мощный и гибкий инструмент для создания композитных приложений, а с другой стороны довольно непонятная и запутанная библиотека. Но можно на PRISM взглянуть и просто как на реализацию шаблона MVVM, чем PRISM для Windows Phone по сути и является.
Мне такая реализация MVVM очень нравится и когда я познакомился с Portable Class Library, я понял, что мне нужен портативный PRISM. Благо исходники PRISM доступны и переделать его на Portable Library было не очень сложной задачей.
Задача собственно состояла в том, чтобы вынести всё общее в портативную часть и всё остальное в специфичную для платформы. Но, кроме того, что мне нравится PRISM, мне ещё нравится использовать его с MEF, а MEF [3] как раз с появлением PCL2.0 появился и для WinRT в виде Microsoft.Composition [4].
К стати, кто не знает, Microsoft.Composition построен на PCL и при желании его можно построить для PCL и использовать в Windows Phone 8 или прямо в портативной библиотеке. Правда вот последней версии исходников, по которым построен NuGet пакет Microsoft.Composition, я на сайте проекта на Codeplex [5] не нашёл.
Так что расширения MEF для PRISM для WinRT пришлось хорошенько изменить с тем чтобы PRISM смог работать с Microsoft.Composition. Тем не менее большинство модульных тестов удалось оставить сделав небольшие изменения.
Кто фундаментально разбирался с тем как работает PRISM знает, что там есть композитные события работа которых требует Dispatcher, а он ведь разный на разных платформах. Кроме того в версии для .NET использовался тип WeakReference [6], которого нет на некоторых платформах. И мне не хотелось бы, вынуждать того, кто будет использовать Portable PRISM каждый раз писать какой-то инициализирующий код, который бы внедрил эти зависимости.
И тут я узнал, что у каждой .NET сборки есть инициализатор – фактически статический конструктор, который выполняется единожды при загрузке сборки в приложение, но так просто его не пропишешь… И тут мне на помощь пришёл великолепный инструмент австралийца Саймона Кроппа (Simon Cropp [7]), Fody [8].
Этот проект родился из проекта расширения для Visual Studio Notify Property Weaver [9], который позволял, используя Mono.Cecil после построения, переписать свойства классов которые были наследниками INotifyPropertyChanged так, чтобы они сами вызывали событие изменения свойства при изменении его значения.
Fody [8] стал более универсальным продолжением Notify Property Weaver [9]’а, к которому можно подключить разные подключаемые модули которые перепишут определённую часть сборки. Для Fody [8] уже написано [10] много полезных модулей [11], которые можно поставить через NuGet в конкретный проект. Одним из таких плагинов является ModuleInit.Fody [12], который умеет прописать в инициализатор сборки вызов метода Initialize статического класса ModuleInitializer.
internal static class ModuleInitializer
{
public static void Initialize()
{
InitializeCompositePresentationEvent();
InitializeWeakEventHandlerManager();
}
private static void InitializeCompositePresentationEvent()
{
var dispatcher = new Lazy<IDispatcherFacade>(() => new DefaultDispatcher());
EventBase.InitializeDispatcher(dispatcher);
}
private static void InitializeWeakEventHandlerManager()
{
EventHandlerManager.Current = new WeakEventHandlerManager();
}
}
Чем я благополучно и воспользовался.
Забавно, но ModuleInitalizer'ы не работают в Windows Phone 7 [13]. И такое впечатление, что никто не собирается исправлять этот баг. Хорошо теперь хоть статические конструкторы работают в подключаемых сборках [14].
WinRT
В версию для WinRT не включены регионы [15]. У меня не было в них необходимости, а написать адаптер для Frame не возможно, так что я решил эту функциональность не переносить. Тем не менее исходники в проекте есть. Так что, вдруг кому-то понадобится их добавить, вы можете это сделать.
Windows Phone 8
В PRISM для Windows Phone 8 я в общем то скопировал функциональность PRISM для Windows Phone 7 добавив лишь WeakEvent так как он теперь доступен в Windows Phone SDK 8.0 и удалил классы касающиеся AppBar так как реализованы они там крайне криво. Я думаю, что гораздо лучше для работы с AppBar использовать библиотеку Cimbalino [16].
И так какие же NuGet пакеты есть:
Я надеюсь, что мои пакеты будут полезны тем кому нравится PRISM или кто хочет что-либо реализованное с использованием PRISM перенести на новую платформу.
Если кому-то нужны другие части PRISM в виде портативной версии, например, расширения для Unity для WinRT вы можете клонировать проект Portable PRISM на GitHub [23] и добавить их. Если не сможете построить проект, пишите. Я ещё не разобрался, как настроить .gitignore так, чтобы информация о NuGet пакетах коммитилась, а сами пакеты – нет, и их можно было повторно скачать. Так что, кто знает, как это сделать, подскажите, пожалуйста.
Автор: XperiAndri
Источник [24]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/27161
Ссылки в тексте:
[1] группы Microsoft Patterns&Practices: http://pnp.azurewebsites.net/en-us/
[2] Microsoft PRISM: http://compositewpf.codeplex.com/
[3] MEF: http://mef.codeplex.com/
[4] Microsoft.Composition: http://nuget.org/packages/Microsoft.Composition/
[5] сайте проекта на Codeplex: http://mef.codeplex.com/SourceControl/list/changesets
[6] WeakReference: http://msdn.microsoft.com/en-us/library/system.weakreference.aspx
[7] Simon Cropp: http://simoncropp.com/
[8] Fody: http://visualstudiogallery.msdn.microsoft.com/074a2a26-d034-46f1-8fe1-0da97265eb7a
[9] Notify Property Weaver: http://visualstudiogallery.msdn.microsoft.com/bd351303-db8c-4771-9b22-5e51524fccd3
[10] написано: https://github.com/Fody
[11] полезных модулей: http://nuget.org/packages?q=fody
[12] ModuleInit.Fody: http://nuget.org/packages/ModuleInit.Fody/
[13] ModuleInitalizer'ы не работают в Windows Phone 7: https://connect.microsoft.com/VisualStudio/feedback/details/775602/wp7-1-1-module-initializers-are-not-executed-for-assemblies
[14] статические конструкторы работают в подключаемых сборках: https://connect.microsoft.com/VisualStudio/feedback/details/722944/windows-phone-static-constructor-is-not-executed-for-class-in-separate-assembly
[15] регионы: http://msdn.microsoft.com/en-us/library/ff921098(v=pandp.40).aspx
[16] Cimbalino: http://cimbalino.org/
[17] Portable PRISM — Portable: https://nuget.org/packages/PortablePrism.Portable/
[18] Portable PRISM — Portable — Interactivity: https://nuget.org/packages/PortablePrism.Portable.Interactivity/
[19] Portable PRISM — WinRT: https://nuget.org/packages/PortablePrism.WinRT/
[20] Portable PRISM — WinRT MEF extensions: https://nuget.org/packages/PortablePrism.WinRT.MEF/
[21] Portable PRISM — Windows Phone 8: https://nuget.org/packages/PortablePrism.WP8/
[22] Portable PRISM — Windows Phone 8 — Interactivity: https://nuget.org/packages/PortablePrism.WP8.Interactivity/
[23] проект Portable PRISM на GitHub: https://github.com/xperiandri/PortablePrism
[24] Источник: http://habrahabr.ru/post/169471/
Нажмите здесь для печати.