Pull to refresh

Portable Prism

Reading time4 min
Views6K
Посвящается фанатам группы Microsoft Patterns&Practices и просто любителям такой полезной штуки как Microsoft PRISM.

Разработчики, которые в своей практике встречались с Microsoft PRISM, вероятно, имеют двоякое мнение об этом фреймворке. С одной стороны, в своей по номеру 4-й, а по порядку 3-й, версии – это очень мощный и гибкий инструмент для создания композитных приложений, а с другой стороны довольно непонятная и запутанная библиотека. Но можно на PRISM взглянуть и просто как на реализацию шаблона MVVM, чем PRISM для Windows Phone по сути и является.

Мне такая реализация MVVM очень нравится и когда я познакомился с Portable Class Library, я понял, что мне нужен портативный PRISM. Благо исходники PRISM доступны и переделать его на Portable Library было не очень сложной задачей.

Портирование


Задача собственно состояла в том, чтобы вынести всё общее в портативную часть и всё остальное в специфичную для платформы. Но, кроме того, что мне нравится PRISM, мне ещё нравится использовать его с MEF, а MEF как раз с появлением PCL2.0 появился и для WinRT в виде Microsoft.Composition.

К стати, кто не знает, Microsoft.Composition построен на PCL и при желании его можно построить для PCL и использовать в Windows Phone 8 или прямо в портативной библиотеке. Правда вот последней версии исходников, по которым построен NuGet пакет Microsoft.Composition, я на сайте проекта на Codeplex не нашёл.

Так что расширения MEF для PRISM для WinRT пришлось хорошенько изменить с тем чтобы PRISM смог работать с Microsoft.Composition. Тем не менее большинство модульных тестов удалось оставить сделав небольшие изменения.

Абстрагирование и Fody


Кто фундаментально разбирался с тем как работает PRISM знает, что там есть композитные события работа которых требует Dispatcher, а он ведь разный на разных платформах. Кроме того в версии для .NET использовался тип WeakReference, которого нет на некоторых платформах. И мне не хотелось бы, вынуждать того, кто будет использовать Portable PRISM каждый раз писать какой-то инициализирующий код, который бы внедрил эти зависимости.

И тут я узнал, что у каждой .NET сборки есть инициализатор – фактически статический конструктор, который выполняется единожды при загрузке сборки в приложение, но так просто его не пропишешь… И тут мне на помощь пришёл великолепный инструмент австралийца Саймона Кроппа (Simon Cropp), Fody.

Этот проект родился из проекта расширения для Visual Studio Notify Property Weaver, который позволял, используя Mono.Cecil после построения, переписать свойства классов которые были наследниками INotifyPropertyChanged так, чтобы они сами вызывали событие изменения свойства при изменении его значения.

Fody стал более универсальным продолжением Notify Property Weaver’а, к которому можно подключить разные подключаемые модули которые перепишут определённую часть сборки. Для Fody уже написано много полезных модулей, которые можно поставить через NuGet в конкретный проект. Одним из таких плагинов является ModuleInit.Fody, который умеет прописать в инициализатор сборки вызов метода 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. И такое впечатление, что никто не собирается исправлять этот баг. Хорошо теперь хоть статические конструкторы работают в подключаемых сборках.

Особенности порта


WinRT
В версию для WinRT не включены регионы. У меня не было в них необходимости, а написать адаптер для Frame не возможно, так что я решил эту функциональность не переносить. Тем не менее исходники в проекте есть. Так что, вдруг кому-то понадобится их добавить, вы можете это сделать.

Windows Phone 8
В PRISM для Windows Phone 8 я в общем то скопировал функциональность PRISM для Windows Phone 7 добавив лишь WeakEvent так как он теперь доступен в Windows Phone SDK 8.0 и удалил классы касающиеся AppBar так как реализованы они там крайне криво. Я думаю, что гораздо лучше для работы с AppBar использовать библиотеку Cimbalino.

Что сейчас доступно?


И так какие же NuGet пакеты есть:


Что дальше?


Я надеюсь, что мои пакеты будут полезны тем кому нравится PRISM или кто хочет что-либо реализованное с использованием PRISM перенести на новую платформу.

Если кому-то нужны другие части PRISM в виде портативной версии, например, расширения для Unity для WinRT вы можете клонировать проект Portable PRISM на GitHub и добавить их. Если не сможете построить проект, пишите. Я ещё не разобрался, как настроить .gitignore так, чтобы информация о NuGet пакетах коммитилась, а сами пакеты – нет, и их можно было повторно скачать. Так что, кто знает, как это сделать, подскажите, пожалуйста.
Tags:
Hubs:
+12
Comments1

Articles

Change theme settings