ReactiveUI, View / ViewModel injection и DI в целом

в последнее время я пытаюсь попасть в новую эру разработки пользовательского интерфейса и обнаружил ReactiveUI. Мне нравится его декларативный характер.

Я хотел сделать полный переключатель, поэтому я попытался понять, как делаются вещи в этом новом мире ReactiveUI. Я выбираю ReactiveUI, потому что я видел, что поддерживается очень умным парнем (Paul C. Betts).

Я очень новичок в этом, и я, вероятно, буду наводнять StackOverflow вопросами об этом, потому что у меня есть огромная сила и Я думаю, он заслуживает того, чтобы его выучили и освоили.

давайте перейдем к деталям:

Я всегда использовал View-First. Я ветеран-пользователь Cinch Framework (http://cinch.codeplex.com/)

Он использует MEF для ввода ViewModels в каждый вид. Вам просто нужно украсить свою ViewModel [ViewModel ("SampleView")] и добавить прикрепленное свойство к вашему представлению (ViewModelLocator.ViewModel= "SampleView"), и всякий раз, когда вид Загруженный, соответствующий ViewModel создается и вводится как его DataContext с выбранным жизненным циклом.

этот механизм, хотя он и действителен, имеет некоторые неудобства. Хуже всего то, что он использует локатор.

Как Марк Seemann предложить в своей книге, ServiceLocator является анти-шаблон, который следует избегать.

  1. Итак, мой первый вопрос: ReactiveUI построен поверх Инфраструктура на основе локаторов?
  2. вид-Первый или Модель Представления-Первых? Что лучше с точки зрения хорошей практики, развязки, твердого тела и подобных вещей, которые являются проблемами сумасшедшего, про-Microsoft чистого любовника кода, как я? Что заставит меня спать лучше и обеспечит мое приложение всеми этими *ibility goodness?

2 ответов


пол, вероятно, вступит в разговор с официальным ответом, но я внесу свои $0.02 как человек, который использовал фреймворк для нескольких проектов, но ни в коем случае не является экспертом.

1) я большой поклонник Марка Seemann, и я согласен с его выводом о ServiceLocator anti-pattern. Хотя ReactiveUI использует локатор "Splat", я бы не считал его построенным поверх инфраструктуры на основе локатора. Есть несколько глобальных элементов, которые используются как планировщики потоков и несколько основные настройки, но они в основном устанавливаются при запуске приложения (как и любой контейнер DI), и вы не имеете дело с ними непосредственно в своих классах по большей части. Единственное реальное местоположение -ViewModelHost управление, которое использует определенный интерфейс (IViewFor) о представлениях для регистрации в ViewModels. Это лучше, чем метод атрибута, так как он держит ViewModels блаженно не знают о представлениях. Но это происходит в самом контроле и является частью структуры, поэтому я не чувствую, что это злоупотребление из ServiceLocator анти-шаблон. Я не чувствую, что это отличается от регистрации ничего в настройка контейнер.

2) только в моем опыте с момента использования ReactiveUI мои взгляды стали супер-простыми. В основном хлопнуть некоторые основные XAML, чтобы получить внешний вид и макет правильно, реализовать IViewFor в коде позади, и сделать все мои привязки в конструкторе, что я нахожу проще теперь с ReactiveUI, чем делать в XAML (хотя вы все еще можете, если хотите). Затем все, что логично, делается в ViewModels. Я думаю, что обычно я делаю первый подход ViewModel исключительно для того, чтобы он (или, по крайней мере, его интерфейс) был определен для реализации IViewFor<> для него на вид. Мне нравится проверка типов и прочее (еще одна причина, по которой мне нравится связываться в конструкторе не в XAML). Но я не думаю, что есть веская причина делать это так или иначе, из моего опыта.


ServiceLocator-это анти-шаблон, которого следует избегать.

Я вообще думаю, что много советов вокруг IoC / DI довольно плохо в области "кросс-платформенных мобильных приложений", потому что вы должны помнить, что многие их идеи были написаны для веб-приложений, а не мобильных или настольных приложений.

например, подавляющее большинство популярных контейнеров МОК касаются исключительно ускорить разрешение на теплый кэша, а в основном, полностью игнорируя использование памяти и время запуска - это 100% хорошо для серверных приложений, потому что эти вещи не имеют значения, но для мобильного приложения? Время запуска огромный.

расположение службы Splat решает ряд проблем для RxUI:

  1. расположение услуги быстро, и почти не имеет накладных расходов для настройки.
  2. он инкапсулирует несколько различных моделей общего срока службы объекта (т. е. " создать новый каждый время", "синглтон", "ленивый"), просто написав Func по-разному
  3. это моно Линкер дружественный (как правило)
  4. расположение службы позволяет нам регистрировать типы в специфичном для платформы коде, но использовать их в коде PCL.

лучший способ использовать Service Locator

на самом деле, я вообще согласен с Марком Seemann, в том, что инъекция конструктора является предпочтительным способом - это шаблон, который я действительно например:

    public SuspensionHost(ISuspensionDriver driver = null)
    {
        driver = driver ?? Locator.Current.GetService<ISuspensionDriver>();
    }

Это использует интерфейс службы, расположенный для интерфейса по умолчанию, но только если вызывающий не дал явного в конструкторе. Гораздо проще тестировать в модульном тестовом раннере, чем пытаться построить поддельный контейнер IoC, но все равно возвращается к реализации по умолчанию во время выполнения.

View-First или ViewModel-First?

можно ли использовать маршрутизацию на основе VM (т. е. RoutedViewHost, IScreen, RoutingState и friends) в ReactiveUI зависит от платформы, на которой вы находитесь:

  • WPF, Xamarin формы: абсолютно
  • WP8, WinRT: вы можете заставить его работать, вы теряете некоторые переходы и тонкости
  • Android, iOS родной: очень трудно сделать работу