I don't know how you faced the fact that Reflector is no longer free, but I for one was very-very dissapointed. Now, our favorite JetBrains team comes to rescue with their brand new tool called dotPeek.
вторник, 24 мая 2011 г.
JetBrains dotPeek to rescue.
понедельник, 16 мая 2011 г.
NServiceBus Saga Idempotency
Should your business entities had a natural identifier (I think even a surrogate one would do in this case), it would be trivial to ensure idempotency of sagas, that drive their processing.


понедельник, 11 октября 2010 г.
Applying monadic combinators to build simple parser
After reading this article, it dawned on me, how easy it might be to write parsers using internal dsl syntax. Looks a bit clumsy in C#, yet rather expressive.
I've used wonderful Magnum library built by Dru Sellers and Chris (creators of open source service bus MassTransit project) as a foundation, since it already contains a base for monadic parsers.
As an example, look how easy it is to write a parser for following simple grammar, describing file version structure:
<version> ::= <part>{<delim><part>|<part>}
<part> ::= <positive integer>+ | <letter>+
<delim> ::= “.” | “,” | “(” | “)” | “ “
And parser in mere 10 lines of code:
Good luck!
среда, 29 сентября 2010 г.
Dependency injection Presentation
На слайдах ниже вы найдете презентацию, которую недавно я провел для своих коллег. Цель ее - завлечь в свою религию, шутка, продемонстрировать наглядно преимущества применения DI вживую. Для оживления презентации, используйте код, выложенный здесь.
P.S. В английской версии блога, я немного порассуждал на тему того, какие "умницы" и как я рад видеть их новые инструменты, но повторяться мне лень . =)
Удачи!
воскресенье, 29 августа 2010 г.
My two cents in OSS. Free VOIP .Net library!
Мои поздравления всем! Только что в сфере .Net стало одной бесплатной VoIP библиотекой больше. Эта библиотека - моя обертка над C-библиотекой pjsip, точнее над ее высокоуровнем API pjsua (user agent).
Работа над ней еще продолжается, но код используется в проектах компании DoxWox, которой выражается отдельное спасибо за возможность опубликовать его. В частности, эта библиотека используется для реализации голосовых конференций в приложении для online общения.
Прошу любить и жаловать: http://code.google.com/p/pjsip4net/
Введение можно почитать здесь:
http://bobbbloggg.blogspot.com/2009/04/designing-managed-api-over-flat-native.html
Частично я уже описывал решения, которыми я руководствовался при создании этой библиотеки, но я планирую более подробно описать здесь внутренности библиотеки, одновременно проводя ее рефакторинг (я, кажется уже упоминал, что работа над ней продолжается ;). Ниже можно почитать о некоторых решениях, примененных в коде:
http://bobbbloggg.blogspot.com/2009/10/detached-template-method-pattern.html
http://bobbbloggg.blogspot.com/2009/09/fluent-builder.html
http://bobbbloggg.blogspot.com/2009/03/initializable-pattern.html
Удачи!
понедельник, 9 августа 2010 г.
Windsor Castle BuildUp
Некоторое время назад я обнаружил, что в лучшем DI-контейнере в .Net сфере Windsor Castle (это мое мнение не подтвержденное никакими фактами, кроме моих высказываний) нет такой простой функциональности как BuildUp. Некоторые из существующих DI-контейнеров, имеют такой метод, а Castle нет. Это неспроста. Я считаю, что BuildUp - это костыль для ситуаций, имеющих более элегантное решение, но бывают случаи, когда он оправдывает себя. Например, когда скорость решения проблемы важна. Под более элегантным решением я понимаю интеграцию с DI-framework, как, например, Castle WCF facility, но понимаете сами, сколько времени и ресурсов нужно для создания полноценного решения.
Должен признаться, что решение оказалось настолько простым, что я в недоумении, почему раньше этого никто не сделал. Хотя чего там, уже написано выше - костыль. Никто не признается просто.
Итак, прежде всего нужно ознакомиться с возможностями расширения Castle. Лазейка для BuildUp - это ComponentActivator. Активаторы вызываются при необходимости создать объект LifetimeManager'ами. Отсюда ограничение решения - с SingletonLifetimeManager оно работать не будет, но и не должно, если подумать. Устанавливая время жизни Singleton вы таким образом явно декларируете, что объектом (коего будет только один экземпляр) владеет контейнер, и создает его он же. А потому BuildUp для такого объекта - вещь бессмысленная.
BuildUpComponentActivator наследуется от DefaultComponentActivator и переопределяет только один метод - Instantiate. В этом методе мы извлекаем уже существующий и созданный вне контейнера экземпляр из контекста. Если в контексте его нет, то мы делегируем работу по созданию объекта базовому классу.
В контекст он помещается в методе расширении контейнера BuildUp как дополнительный параметр в IDictionary:
Для того, чтобы объект мог быть пропущен через BuildUp, в компонентной модели для него следует установить ComponentActivator. CanBeBuiltUp оборачивает такой вызов для castle Fluent registration API.
Я говорил, что решение удивительно простое? Это результат работы коллектива очень талантливых людей, к коим я не принадлежу, если чо. =)
Удачи!
четверг, 24 июня 2010 г.
Trigger Caliburn action status update through Prism's IEventAggregator
И Caliburn и Prism, в принципе решают одни и те же задачи - создание композитных приложений на WPF. Но, вот Роб Эйзенберг (создатель Caliburn) не считает, что они друг друга взаимоисключают, а я и подавно с ним согласен.
Я использую следующие "фичи" Prism'a:
- modularity;
- region manager;
- event aggregator;
- actions engine;
- application & model framework, даже не смотря на то, что с первого взгляда model framework кажется "overarchitected";
- convention over configuration;
Главный способ расширения - это написание фильтров, которые вставляются в последовательность выполнения action. С их помощью можно проверять предусловия или состояние данных (к примеру можно проверить обладает ли Principal достаточными правами для выполнения действия), дабы определить статус action и обновить эффекты, применяющиеся к UI элементам. Примером такого фильтра является поставляющийся с framework фильтр Dependencies, который вызывает исполнение всей последовательности фильтров, на основании изменения какого-либо свойства, имя которого передается в качестве параметра ему. Но что, если вам нужно просто обновлять статус action, не связанный ни с каким полем в объекте, на основании какого-либо события/условия. Вы можете завести специальное поле и передергивать его значение или даже еще лучше - не заводите никакого поля, а просто кидайте нотификацию с именем несуществующего поля, переданного фильтру. Не знаю как вам, а у меня от таких решений зудит в одном месте.
Так вот зуд мой унялся только когда я написал фильтр, запускающий всю цепочку обработки статуса события по получению уведомления от EventAggregator сервиса Prism.
DependsOnEvent

Фильтр применяется как атрибут, которому передается тип события. Тут есть одно ограничение - событие должно быть унаследовано от generic типа CompositePresentationEvent закрытого типом object, т.е. CompositePresentationEvent_Of_Object. В методе Initialize происходит магия с помощью reflection. Дело в том, что IEventAggregator Prism имеет исключительно generic интерфейс, за что можно разработчиков его только поругать. Мы получаем событие переданного типа и подписываемся на него. Вот именно для этого и приходится колдовать с волшебным зеркальцем, т.к. заранее тип события не известен. Часть, относящуюся к запуску обработки action, я содрал из кода упомянутого выше Dependencies фильтра.

Здесь мы создаем Observer, который будет следить за изменениями зависимых свойств. Т.к. реально никакие свойства не меняются я просто использую трюк с несуществующим свойством - в Initialize при подписке на событие я передаю делегат, который кидает событие обновления свойства Update, которого-то как раз и нет. Observer, поймав это событие запускает всю цепочку обновления статуса action.

PublishEventAfter
Ну и напоследок, фильтр, выполняющий все ровно наоборот, после выполнения action он кидает событие, которое обрабатывает EventAggregator.

Удачи!
