Внедрение Notification Bar

Сложность 100

В прошлый раз я провел общий обзор компонента Notification Bar, рассказал как он работает, возможности, планы по развитию. Немного коснулся того, как модифицировать код, чтобы можно было внедрить Notification Bar (NB), насколько мало надо действий для этого. В этом посте я хочу детально разобрать о том, как внедрить систему уведомлений в приложение, и, я надеюсь, вы согласитесь с тем, что это сделать весьма просто.

Установка

Начнем с установки компонента. Это можно сделать с помощью NuGet пакета следующей командой:

Install-Package VioletTape.NotificationBar

При установке будут подгружены так же все зависимые компоненты и пакеты:

  • PostSharp Free Community Edition
  • PostSharp Threading Toolkit
  • PostSharp Domain Toolkit
  • Rx Framework
  • StructureMap
  • MakeMeAsync

Данный пакет необходимо будет установить для сборки с UI компонентами и для сборки с моделями.

UI настройка

Естественно, что для любой технологии и для любого компонента всегда есть некоторые ограничения и необходимые начальные условия. Так что предлагаю рассмотреть некоторые необходимые начальные условия для Notification Bar. На данный момент такими естественными ограничениями являются технологии:

  • .Net Framework 4.5
  • Windows Presentation Framework

Это в некотором роде базис, ограничения самой платформы. Следующее требование вам придется реализовывать самостоятельно, но это на мой взгляд минимальные ограничения на ваш продукт. Итак, необходимо реализовать интерфейс

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

В этом месте стоит остановится поподробнее и рассказать об общей системе приложений, о системе UI.

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

Подробнее

Notification Bar Overview Video

Сегодня я хочу для затравки показать функционал визуального компонента, который позволяет отображать внутрипрограммные уведомления в системном стиле. Причем для включения функционала не потребуется переработки моделей в общем случае. Но все подробности потом, а обзорное видео подкатом!

Notification Bar Overview

Валидация свойств с помощью атрибутов в WPF

Сложность 200-300

Уже очень давно меня не оставляет мысль о глобальной несправедливости для WPF в плане валидации свойств по сравнению с ASP.NET. Какое-то время хотелось даже самому взяться за это дело, но внутренне я понимал, что это не у меня одного такое ощущение и должны быть где-то уже реализации данного функционала в удобной и доступной форме, когда не нужно писать самому кучу кода, дополнительных свойств приаттаченых, или еще чего-нибудь в таком духе. Большинство статей на CodeProject по теме валидации свойств в WPF очень стары и предлагают написать очень много кода самому, но хочется ведь чтобы почти все стандартные простые проверки ввода уже работали из коробки.

Так как в последнее время опять я взялся крепко за PostSharp, то не мог не просмотреть страничку с упоминанием проектов основанных на PostSharp и среди них оказался интересный проект Wakizashi. Суть данного проекта сводится к тому, чтобы реализовать проверку свойств с помощью атрибутов.

Традиционный способ валидации

Традиционным способов валидации пользовательского ввода в большинстве случаев было написание кода в лоб, что не добавляло элегантности коду и затрудняло его чтение. При большом количестве проверок это могло даже стать монструозным. Ко всему прочему такой способ проверок не дает быстрой реакции на ввод информации пользователем и информирует не самым приятным способом.

Подробнее

PostSharp Threading Toolkit

Сложность 100

В завершении небольшого цикла о PostSharp Toolkits стоит так же поведать о средстве для обнаружения дэдлоков в программе. Для внедрения такого функционала потребуется по одной строке кода в AssemblyInfo.cs в каждом проекте, зато польза должна быть ощутимой. Но обо всем по порядку. В работе приложений большей всего раздражает «замерзший» интерфейс. Причин для этого может быть много: как неправильно распределенные операции по потокам, но через какое-то время интерфейс отмирает, так и дэдлоки в программе, которые вешают приложение намертво.

Определение для deadlock

Deadlock – ситуация когда два или более ресурса ждут завершений действий друг друга, но так никогда и не дожидаются. Если вы обширно используете конструкцию lock, то потенциально вы можете оказаться в описанной ситуации. Существует 4 основных условия для возникновения дэдлока:

  1. Ограниченное количество экземпляров для ресурса. В случае использования класса Monitor в С#, это число ограничено 1 экземпляром, так как Monitor создает взаимоисключающую блокировку. Напоминаю, что lock{…} это синтаксический сахар для класса Monitor.
  2. Возможность удерживать один ресурс и одновременно запрашивать другой. В C#, как и в большинстве языком, это проделывается легко, например:
  3. Отсутствие преимущественного освобождения ресурсов. В C# это значит, что один поток не может заставить другой поток освободить ресурсы.
  4. Цепная зависимость условий ожидания. Пусть поток 1 ожидает поток 2, поток 2 ожидает поток 3, а поток 3 ожидает 1. Получилась цепная зависимость, которая приводит к дэдлоку.

Если какое-либо условие исключить, то взаимная блокировка ресурсов невозможна. Логично предположить, что для решения проблемы дэдлоков необходимо чтобы хотя бы одно условие не выполнялось в любой момент работы приложения. К сожалению для больших систем описанные условия возникновения дэдлоков возникают на удивление просто. В теории, взаимная блокировка ресурсов может быть решена путем прекращения одного из потоков, который вовлечен в создание дэдлока. В то же время в большинстве ситуаций прерывание потока опасная операция, так как при этом данные должны быть корректно возвращены в исходное состояние. Некоторые продвинутые техники, такие как lock leveling могут предотвратить появление блокировок. При использовании упомянутой техники, все блокировки получают свой номер и поток может получить только блокировки с номером больше своего. В целом можно представить сложность данного решения и что такой подход может лишить нас многих плюшек .Net Framework, так что это не из разряда практических решений задач.

Подробнее

PostSharp Thread\Dispatcher Toolkit

Сложность 100

Сегодня я хочу рассказать о еще одном тулките от PostSharp, который позволяет сократить количество служебного кода на порядок. Впрочем, любое решение с помощью PostSharp сильно облегчает работу программиста, позволяя избавиться от повторяющегося кода, вынеся его в отдельный класс.

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

О том как решаются эти проблемы в «традиционном» стиле, я рассказывал в статье про эволюцию сервисных методов, там же описана библиотека MakeMeAsync, которой я с удовольствием и активно пользуюсь на данный момент. Не буду повторятся какие альтернативы существуют. Сейчас уже официально выпущен .Net Framework 4.5 c поддержкой конструкции async\await, так что я надеюсь что использование монструозных конструкций для выполнения кода асинхронно будет сходить на нет.

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

Подробнее

INPC Framework

Сложность 100

Уже не первый раз я поднимаю тему о INotifyPropretyChaned, так как это постоянно мозолит глаза и заставляет придумывать разные подходы к реализации этого функционала. Постоянно разгораются споры как лучше реализовать интерфейс. Примерно раз в месяц попадается статья на CodeProject о том, как совладать с этим интерфейсом, поэтому я не буду больше разоряться о том, какие плюсы и минусы несет ручная реализация, или же реализация с помощью других средств.

Некоторые библиотеки по реализации интерфейса предлагают в «полезную нагрузку» IoC контроллеры и перехватчики в стиле АОП.

Хотя до недавнего момента я использовал часто Kind Of Magic для решения этой проблемы, я неоднократно сталкивался с тем, что люди в свойства запихивают огромный функционал и этим отрицают целесообразность использования средств в духе Magic. Либо же начинают рассказывать о том, что должен быть полный контроль кода – все надо писать руками.

Относительно давно были анонсы о фремворке от Sharpcrafters, но я как-то пропускал их в силу разных причин и загруженности, но наконец дошли руки и я хочу вам рассказать о PostSharp Domain Toolkit, он же INPC Framework.

Коротко о главном

Распространяется PostSharp Domain Toolkit c помощью NuGet пакета. Установить его можно выполнив команду:

Install-Package PostSharp.Toolkit.Domain

После чего установится как сам тулкит, так и PostSharp. Можно начинать работу.

Самый простой и общий сценарий будет заключатся в добавлении атрибута NotifyPropertyChanged к вашей вьюмодели. Всё. Больше ничего делать не надо. Автоматически «магическим» образом будут обработано подавляющее большинство всех сценариев работы в среднестатистическом приложении.

Подробнее

Self-Tracking Objects

Сложность 400

Долго думал как можно по-русски кратко и красиво назвать статью, но не придумал ничего хорошего, поэтому оставляю как есть на английском, так как это наиболее ёмко и в полной мере отражает характер тех объектов, что мы будем описывать. А под описание сегодня у нас попадают объекты, которые могут отслеживать изменения в себе на уровне полей/свойств.

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

Подробнее

Postsharp: авторизация и аутентификация

Одно из самых востребованных применений аспектно-ориентированного программирования это вынос обслуживающего инфраструктурного кода, который часто повторяется в системе, в отдельный класс. Что в свою очередь является проявленем принципа единой ответственности (SRP — Single Responsibility Principle). Очень часто задачи авторизации и аутентификации разбросаны по всему коду проверяя права доступа пользователя. Следствием этого является большая трудоемкость изменений в этой немаловажной части логики, а так же ее общая проверка. Принцип единой ответственности говорит о том, что должна быть только одна причина для изменения класса, так что все что относится к авторизации и аутентификации просто просится в отдельные классы.

Основные методы аутентификации обычно не то, что используется по всему приложению. Например в веб приложениях ввод данных для аутентификации и сама аутентификация происходит на одной странице, после чего информация о пользователе хранится в каком-либо токене со сроком годности. Благодаря этому пользователь может автоматически входить в систему в течении срока работы токена. Таким образом единственным кодом, который пронизывает все страницы приложения будет проверка того, что пользователь до сих пор в системе. Конечно, вы можете использовать PostSharp для такой проверки, но это не лучший способ применения, по моему мнению.

Подробнее

Ненавистный INotifyPropertyChanged

Да, уже из названия видно мое отношение к интерфейсу INotifyPropertyChanged и к его явной реализации в проекте. Я покрываюсь мурашками, и меня бросает в дрожь только при одном виде такого кода:

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

А когда таких свойств прописано с десяток и все это обернуто в регион (#region), то взгляд стекленеет, становится безжизненным и мозг отказывается верить в реальность происходящего. Конечно, самое большое зло от такого подхода – потеря времени на написание и на чтение.

Более того, это чистый инфраструктурный код, который не должен попадаться на глаза в логике приложения, только если специально его искать. Реализация INotifyPropertyChanged прямой и явный кандидат на реализацию в рамках аспектного-ориентированного программирования.

К сожалению, при разработке пользовательского интерфейса на WPF такая реализация «в лоб» встречается до сих пор сплошь и рядом. Не далее чем неделю назад вычищал такой код из рабочего проекта. Я бы порадовался за трудолюбие и усидчивость разработчиков пишущих такой код, но я склонен думать, что программист должен быть ленивым. В хорошем смысле. Так что лучше потерять немного времени на настройку и потом быстро-быстро все сделать. Далее я опишу 4 более-менее различных подхода к решению данной проблемы.

Подробнее

PostSharp. Безопасность полей класса

И снова речь пойдет о PostSharp! =) Сегодня я хочу рассказать об аспекте OnFieldAccess (или в версии 2.0 LocationInterceptionAspect), который позволяет держать контроль над использованием свойств и полей класса. В прошлых статьях я рассказывал о применении аспектов на вызовы методов и о задачах, которые могут быть решены с их помощью. В целом, все те же задачи применимы и к полям: логирование изменения значений полей, защита доступа по ролям. Кроме этого можно организовать защиту полей от записи, декларативную проверку значений, уведомление других объектов об изменении значений.

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

Так же, в этой статье я рассмотрю такую возможность PostSharp, как проверка возможности применения аспекта на этапе компиляции. Я считаю, что это замечательная возможность, которой не стоит пренебрегать в дальнейшем. Для кого-то это может даже стать решающим моментом в применении данного продукта. Я знаю таких людей, которые ни за что не будут пользоваться продуктом, который не будет их строго ограничивать, а тут они имеют возможность написать себе такие ограничения и радоваться жизни. Да и в случае дистрибуции третьим сторонам вашей библиотеки это будет полезно.

Подробнее