Подтвердить что ты не робот

Агрегирование событий Prism - абонент не запускается

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

Сделано предположение: мне не нужно настраивать IEventAggregator где угодно - например. регистрироваться в контейнере IoC? Это встроено в Prism, так что у меня есть только один экземпляр агрегатора событий, правильно?

Итак, вопрос в основном заключается в том, как/где/, когда я должен настроить своих подписчиков. Есть ли определенный заказ на вещи и т.д.? В моем упрощенном примере у меня есть один модуль MyModule. Bootstrapper добавит MyModule в каталог - инициализирует его:

catalog.AddModule(typeof(MyModule));

MyModule будет хранить агрегатор и использовать его для подписки на MyModuleRequestedEvent. Он также использует реестр меню для регистрации в меню приложения. Идея состоит в том, что в конечном итоге щелчок в меню должен инициировать событие - уведомление MyModule о том, что оно было запрошено. Затем я хочу, чтобы это была ответственность MyModule, чтобы выяснить, что делать дальше.

public MyModule(IEventAggregator aggregator, IApplicationMenuRegistry menu)
{
    _applicationMenu = menu;
    _aggregator = aggregator;
}

public void Initialize()
{
    var evnt = _aggregator.GetEvent<MyModuleRequestedEvent>();
    evnt.Subscribe(MyModuleRequested);
    _applicationMenu.RegisterMenuItem("MyModule", evnt);
}

public void MyModuleRequested(bool b)
{
    MessageBox.Show("MyModule requested");
}

Теперь у меня есть кнопка в моей оболочке, которая опубликует это событие. Оболочка получает тот же (?) Агрегатор событий при его разрешении.

public Shell(IEventAggregator aggregator)
{
    InitializeComponent();
    var evnt = aggregator.GetEvent<MyModuleRequestedEvent>();
    EventTriggerButton.Click += (s, e) => evnt.Publish(true);
}

Примечания:

  • Подтвердили, что событие опубликовано. Добавление подписчика в оболочку также приведет к тому, что этот абонент получит событие.
  • Снова; абонент в MyModule не запускается. Однако, как это ни странно, это было несколько раз.
  • Я не использую вход для события. Казалось, что вам нужен какой-то входной тип, поэтому я просто пошел с манекеном. Могу ли я избавиться от этого...?
4b9b3361

Ответ 1

Агрегатор событий Prism использует слабые ссылки для ссылки на события. Это делается для предотвращения утечек памяти из обработчиков событий.

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

evnt.Subscribe(MyModuleRequested, true);

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

Ответ 2

Итак, я только что получил теорию, но не время проверять ее прямо сейчас.. Будет делать завтра.

Вопрос: Будет ли добавление модулей в ModuleCatalogue сохранить их в живых? Я предположил, что так будет. Следовательно - MyModule должен оставаться в живых - и затем будет срабатывать при публикации события.

protected override IModuleCatalog GetModuleCatalog()
{
    var catalog = new ModuleCatalog();
    catalog.AddModule(typeof(MyModule));
    return catalog;
}

Однако, если это не поддерживает модуль, очевидно, что ему будет сложно ответить на событие. Модуль-объект умирает, но он не отменяет подписку - поэтому я увижу подписчика в списке EventAggregator, но подписчика больше нет. Также; Я упомянул, что я на самом деле иногда работаю - что было бы, если сборщик мусора не успел вытащить мусор перед тем, как событие будет запущено.

Звучит ли это так? Если это так - я еще не думал о решении, поэтому вы можете предложить его в другой ответной теме.

Итак, что такое ModuleCataloge? Только список сохранен для Инициализации, а затем выброшен?