Изначально EventPublisher прездназначался для отправки сообщений экземплярам классов, которые уже существуют, и явным образом подписаны. Но часто полезно, когда получатель сообщения не живёт постоянно, а создаваётся во время его отправки, и время жизни ограничено временем обработки сообщения. Такой вот одноразовый обработчик: создался, обработал, испарился. Такую вещь можно реализовать как рефлексивный IListenerSource. Но этот способ не лишён недостатков, главный из которых - сложности с управлением зависимостями.
К счастью, в этом мире проблема управления зависимостями уже решена с помощью DI контейнеров. Осталось только выбрать контейнер, и написать основанный на контейнере IListenerSource. Не буду скрывать, мой любимый контейнер - Castle.Windsor. Его и буду использовать.
Перед написанием собственно IListenerSource, стоит подумать об еще одной вещи: как регистрировать наших подписчиков в контейнере? Windsor широко использует принцип convention over configuration, и имеет множество встроенных средств для регистрации компонентов по соглашением. Значит надо такое соглашение придумать. Вот оно:
Следующий логичный шаг - это регистрация обработчиков событий в контейнере. Конечно, в каждом проекте это придётся делать по-новому, но было бы неплохо написать помощника в этом нудном деле. Я не буду приодить его здесь, дабы не загромождать блог кодом, но можно посмотреть на github.
Теперь у нас есть всё для создания IListenersSource: соглашение о подписчиках и инструмент их регистрации. С Windsor'ом это совсем не сложно:
Остался последний штрих. Windsor предлагает еще одну концепцию для упрощения рутинных действий при регистрации компонентов: Facility. Почему бы не сделать EventPublisherFacility?
Основые действия, которые на неё возлагаюстся:
Надеюсь, это материал будет кому-нибудь полезен. Код проекта на github.
К счастью, в этом мире проблема управления зависимостями уже решена с помощью DI контейнеров. Осталось только выбрать контейнер, и написать основанный на контейнере IListenerSource. Не буду скрывать, мой любимый контейнер - Castle.Windsor. Его и буду использовать.
Перед написанием собственно IListenerSource, стоит подумать об еще одной вещи: как регистрировать наших подписчиков в контейнере? Windsor широко использует принцип convention over configuration, и имеет множество встроенных средств для регистрации компонентов по соглашением. Значит надо такое соглашение придумать. Вот оно:
public interface ITransientListener<TMessage> : IListener<TMessage> { }Как можно догадаться из названия - регистрировать подписчиков будем с Transient Lifestyle, чтобы обеспечить желаемый стиль работы: создался, обработал, испарился.
Следующий логичный шаг - это регистрация обработчиков событий в контейнере. Конечно, в каждом проекте это придётся делать по-новому, но было бы неплохо написать помощника в этом нудном деле. Я не буду приодить его здесь, дабы не загромождать блог кодом, но можно посмотреть на github.
Теперь у нас есть всё для создания IListenersSource: соглашение о подписчиках и инструмент их регистрации. С Windsor'ом это совсем не сложно:
public class TransientSource : IListenerSource { private readonly IKernel _kernel; public TransientSource(IKernel kernel) { _kernel = kernel; } public virtual IEnumerable<IListener<TMessage>> ResolveListenersFor<TMessage>() { return _kernel.ResolveAll<ITransientListener<TMessage>>(); } }Теперь мы можем сконфигурировать EventPublisher, чтобы он перенаправлял сообщения одноразовым обработчикам из контейнера. Но как же быть со старыми добрыми долгоживущими экземплярами подписчиков? Ответ прост: нужен источник подпичиков, который бы аггрегировал подписчиков из разных источников - CompositeListenerSourсe.
Остался последний штрих. Windsor предлагает еще одну концепцию для упрощения рутинных действий при регистрации компонентов: Facility. Почему бы не сделать EventPublisherFacility?
Основые действия, которые на неё возлагаюстся:
- Конфигурирует EventPublisher используя IPublishWay зарегистрированный в контейнере или переданный в конструкторе, и CompositeListenerSource, в который добавлены TransientListnerSource, и все зарегистрировные в контейнере IListenerSource.
- Регистрирует в контейнере IAssignee, для возможности добавлять подписчиков.
Надеюсь, это материал будет кому-нибудь полезен. Код проекта на github.
Комментариев нет:
Отправить комментарий