Вопрос

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

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

Итак, вопрос в основном заключается в том, как / где / когда я должен настроить своих подписчиков.Есть ли конкретный порядок в отношении материалов и т.д.?В моем упрощенном примере у меня есть один модуль MyModule.Загрузчик добавит 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 не запускается.Однако это - как ни странно - было в нескольких случаях.
  • Я не использую входные данные для события.Казалось, что вам нужен был какой-то тип ввода, поэтому я просто выбрал фиктивный bool.Могу ли я избавиться от этого ..?
Это было полезно?

Решение

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

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

evnt.Subscribe(MyModuleRequested, true);

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

Другие советы

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top