понедельник, 1 февраля 2010 г.

Заменяем механизм событий в CAB

Стандартный механизм событий в CompositeUI Application Block'е (CAB) не устраивает меня по нескольким причинам:
  1. Сложно и не удобно использовать. Нужно объявить событие, пометить его аттрибутом, потом сделать метод, который будет проверять на непустой список подписчиков и уже этот метод вызывать для генерации события.
  2. Отсутствие строгой типизации. Никто не мешает объявить подписку на событие с одной сигнатурой, а сгенерировать событие с другой.
  3. Неудобно отлаживать и разбираться в коде. Для того чтобы найти "подписчиков" и "публикаторов" события, приходится искать по строковому литералу.
  4. Неявная регистрация через рефлексию. А значит это не фатально, но медленнее чем могло бы быть.
Почитав Jeremy Miller's "Build Your Own CAB" и посмотрев на исходники StoryTeller, не мог удержаться от того, чтобы сделать что то подобное:

    public interface IListener<T> : IListener
    {
        void Handle(T message);
    }

    public interface IEventAggregator
    {
        void AddListener(IListener listener);
        void RemoveListener(IListener listener);
 
        void SendMessage<T>(T message);
        void SendMessage<T>() where T : new();
    }

После чего всё становится до неприличия простым:

    class MultiListener : IListener<Message1>, IListener<Message2>
    {
        public MultiListener(IEventAggregator eventAggregator)
        {
            // This is sample code!
            // Don't forget to unsubscribe in production code!
            eventAggregator.AddListener(this);
        }
 
        public void Handle(Message1 message)
        {
            Console.WriteLine("Message1");
        }
 
        public void Handle(Message2 message)
        {
            Console.WriteLine("Message2");
        }
    }

Исходный код можно взять здесь.

P.S. А мне начинает нравиться coding style, когда приватные методы начинаются с lower case.

P.P.S. До конца не уверен, что это окончательный вариант с "синхронизированными" "подписчиками". Что если потоков много и я хочу получать свои сообщения в том же потоке, в котором я подписывался? Надо обдумать...
Wider Two Column Modification courtesy of The Blogger Guide