Monday, April 20, 2015

Обновляем MvvmLight до последней версии

Сегодняшнюю статью я хотел бы посвятить библиотеке для работы в WPF, которая отлично ложится на использование паттерна MVVM. Поговорим о прекрасном наборе компонентов, разработанном компанией GalaSoft под названием MVVM Light Toolkit. В 2013 году я уже писал статью об этой библиотеке под названием 'MVVM Part 2', в которой на простом примере описывал, как ее использовать. С этих пор много чего изменилось. Сейчас этот набор компонентов доступен в NuGet Package Manager как в виде отдельных библиотек, так и целого набора компонентов.
Данная библиотека постоянно дописывается, изменяется, улучшается. Например, последние изменения в этой библиотеке на момент написания статьи были добавлены 15.02.2015. Библиотека может быть использована для WPF, WindowsPhone, Windows Store Apps и т.д. Везде, где есть разметка XAML, ее можно использовать. Она в два раза популярнее, чем фреймворк для построения WPF приложений на базе паттерна MVVMPrism.
Еще она в два раза популярнее аналогичного Prism фреймворка, который покрывает также разработку под мобильные устройства – Caliburn.Micro.
В этой статье я не буду писать примеры использования этой библиотеки. Для этого можете обратиться к моей статье по приведенной выше ссылке. Рассмотрим эту библиотеку с точки зрения разработчика, которому в крупном проекте нужно сделать рефакторинг и обновить GalaSoft.MvvmLight.dll с версии 2.0.0.0 до последней актуальной версии на момент написания статьи, а именно: версии 5.1.1.0. Мы будем добавлять множество сравнений и картинок, поэтому надеюсь, что статья получится увлекательная. Первым делом мы сравним эти две библиотеки на предмет изменений в них.
Начнем, пожалуй, с пространства имен GalaSoft.MvvmLight.
Хорошая новость звучит в том, что вам нужно будет по минимуму провести модификаций, чтобы ваш код заработал. Наконец-то разработчики MvvmLight продумали все нюансы с обновлением свойств, очисткой модели и т.д., а также сделали все по максимуму через интерфейсы.
Следующим идет пространство имен MvvmLight.Command. Здесь производился в основном рефакторинг и исправление некоторых ошибок, выявленных заранее. Сама реализация особо не изменилась, как минимум, ничего в коде вам менять не придется.
Результат использования после обновления можно посмотреть ниже.
private RelayCommand<string> _copyToClipboardParameterCommand;
public RelayCommand<string> CopyToClipboardParameterCommand
{
    get
    {
        return _copyToClipboardParameterCommand ??
                (_copyToClipboardParameterCommand = new RelayCommand<string>(CopyToClipboardExec, _ => true));
    }
}
А вот пространство имен MvvmLight.Helpers претерпело множество обновлений.
Обратная совместимость при этом работает достаточно хорошо, и ничего не сломалось, а добавление новой функциональности связано в первую очередь с поддержкой множества платформ (Silverlight, WinRT и других).
С пространством MvvmLight.Messaging же случилась настоящая беда из-за огромного количества изменений.
В первую очередь, изменения касаются класса DialogMessage, с помощью которого можно раньше было создавать диалоговые окна с ViewModel. Это привело к тому, что многие участки кода в нашем проекте просто-напросто попадали.
private void ShowMessage(DialogMessage message)
{
    Message = new MessageVM(message.Content, message.Caption, message.Button,
        message.Icon, res =>
        {
            message.Callback(res);
            Message = null;
            IsBlocked = false;
        });
    IsBlocked = true;
}
Хотя в рефакторинге, который проделали разработчики GalaSoft, есть и большой плюс.
Во-первых, получился более-менее стандартизированный интерфейс, который позволяет расширять его для разных платформ. Во-вторых, последняя реализация стала напоминать реализацию в таких фреймворках, как Prism и Caliburn.Micro.
Минусы: теперь вы не сможете указывать, какие кнопки должны быть отображены на интерфейсе, а также не сможете использовать полноценно установку иконок и т.д. Получился очень и очень ограниченный интерфейс.
Класс DialogMessage убрали, начиная с версии 4.3.31. Основная причина, по которой отказались от использования этого класса – это использование 'view enumarations', таких как MessageBoxButton и MessageBoxResult (дополнительную информацию можно посмотреть в блоге galasoft). Правда, разработчики потрудились написать целую статью 'Messenger and View Services in MVVM' в MSDN Magazine о том, как использовать новый сервис. Поскольку нам было не с руки реализовывать интерфейс через таски (ломало очень много логики), пришлось вернуть ту реализацию, которая была в старой версии MvvmLight.
public class DialogMessage : GenericMessage<string>
{
    public MessageBoxButton Button
    {
        get;
        set;
    }
    public Action<MessageBoxResult> Callback
    {
        get;
        private set;
    }
    public string Caption
    {
        get;
        set;
    }
    public MessageBoxResult DefaultResult
    {
        get;
        set;
    }
    public MessageBoxImage Icon
    {
        get;
        set;
    }
    public MessageBoxOptions Options
    {
        get;
        set;
    }
    public DialogMessage(string content, Action<MessageBoxResult> callback)
        : base(content)
    {
        this.Callback = callback;
    }
    public DialogMessage(object sender, string content, Action<MessageBoxResult> callback)
        : base(sender, content)
    {
        this.Callback = callback;
    }
    public DialogMessage(object sender, object target, string content, Action<MessageBoxResult> callback)
        : base(sender, target, content)
    {
        this.Callback = callback;
    }
    public void ProcessCallback(MessageBoxResult result)
    {
        if (this.Callback != null)
        {
            this.Callback(result);
        }
    }
}
В новой версии увеличилось количество сборок, которые добавляются в проект. Теперь их как минимум 3.
В этом нет никаких проблем. Разве только в том, что сейчас добавлена завязка на сборку Microsoft.Practices.ServiceLocation, который предоставляет для нас интерфейс IServiceLocator и реализацию паттерна ServiceLocator. Тем, кто использует данный антипаттерн, это не составит проблем, но так как в нашем проекте мы стараемся не использовать ServiceLocator, это создает свои трудности.

На этом закончим разбор различий между разными библиотеками MvvmLight, и в одной из следующих статей постараемся рассмотреть сравнение MvvmLight с такими популярными фреймворками, как Prism и Caliburn.Micro.  

No comments:

Post a Comment