Пользовательский агрегатор событий в приложении winforms MVP

Я решил создать свой собственный агрегатор событий для приложения winforms MVP, которое я пишу. Цель состоит в том, чтобы позволить представлениям (пользовательским элементам управления) подписываться на события из моделей, которые в противном случае имеют свои представления.

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

Мои предложения на данный момент:

  1. Я думаю, что его внедрение было бы беспорядком, поскольку все пользовательские элементы управления должны иметь IEventAggregator, а агрегатор не нужен для самого пользовательского элемента управления, а только для основного приложения, которое состоит из пользовательских элементов управления с дополнительными функциями.
  2. Делаем EventAggregator статическим или одноэлементным. Это, однако, создало бы аналогичную проблему, когда отдельные пользовательские элементы управления должны были бы публиковать события через статический агрегатор.

У вас есть какие-нибудь идеи, чтобы помочь мне?


person kasperhj    schedule 19.09.2012    source источник
comment
Вы поняли это? Почему вы думаете, что инъекция будет беспорядок? Как бы вы протестировали взаимодействие с агрегатором управления ‹-› без какой-либо имитации агрегатора? (В MVP сами элементы управления остаются без параметров в их ctor; у них есть презентаторы, которые обрабатывают зависимости).   -  person Fred    schedule 27.07.2013
comment
Нет. Я решил использовать WPF с Caliburn, в который встроен советник :)   -  person kasperhj    schedule 01.08.2013
comment
Хороший выбор. Я работал с Caliburn.Micro над некоторыми проектами SL — все преимущества Caliburn с меньшим количеством кода caliburnmicro.codeplex.com - стоит посмотреть, если вы делаете что-то, связанное с xaml. Что касается общей реализации только советника, если вы знакомы с Rx (Reactive Extensions) и IObservable, посмотрите joseoncode.com/2010/04/29/   -  person Fred    schedule 01.08.2013


Ответы (1)


Я реализовал простой EventBroker для такого сценария. Тем не менее, я не думаю, что инъекция будет беспорядком. На самом деле, внедрение его в контейнер, а затем разрешение на публикацию/подписку было бы самым аккуратным способом. Также было бы проще провести модульное тестирование. Мой брокер событий приведен ниже (я использую MEF, но это вряд ли будет иметь какое-либо значение): -

  [Export]
public class MyEventBroker : IMyEventBroker
{
    [ImportingConstructor]
    public MyEventBroker()
    {

    }

    private readonly ConcurrentDictionary<Type, List<Action<CompositeEventArguments>>> _compositeEventHandlers = new ConcurrentDictionary<Type, List<Action<CompositeEventArguments>>>();

    public void Publish<T>(CompositeEventArguments args)
    {
        if (_compositeEventHandlers.ContainsKey(typeof (T)))
        {
            _compositeEventHandlers[typeof(T)].ForEach(subscriber=> { if (subscriber != null) subscriber.Invoke(args); }); //TODO : check for null. QUES - Will we need weak references?????
        }
    }

    public void Subscribe<T>(Action<CompositeEventArguments> handler)
    {
        if (!_compositeEventHandlers.ContainsKey(typeof (T)))
            _compositeEventHandlers[typeof(T)] = new List<Action<CompositeEventArguments>>();

        _compositeEventHandlers[typeof (T)].Add(handler);

    }

    public void UnSubscribe<T>(Action<CompositeEventArguments> handler)
    {
        if (_compositeEventHandlers.ContainsKey(typeof (T)))
            _compositeEventHandlers[typeof (T)].Remove(handler);

    }
}

public class CompositeEvent<T> where T : CompositeEventArguments
{

}

public class CompositeEventArguments
{

}

Теперь, чтобы иметь собственное событие, определите аргументы события: -

#region Custom Events
public class MyCustomEventArgs : CompositeEventArguments{}
#endregion

Затем опубликовать: -

        var broker = MefContainer.Instance.Resolve<MyEventBroker>();
        broker.Publish<MyCustomEventArgs >(new MyCustomEventArgs());

И подписаться:-

            var broker = MefContainer.Instance.Resolve<MyEventBroker>();
            broker.Subscribe<MyCustomEventArgs >(t=>MyHandler(t));

MefContainer — это мой настраиваемый одноэлементный класс для представления контейнера композиции. Вы можете использовать Unity, Windsor или что угодно!

Об этом написано в блоге здесь: http://compositewinform.blogspot.co.uk/2014/04/have-you-ever-found-yourself-in.html

person Shivakant Upadhyay    schedule 24.04.2014