.net Prism事件聚合-未触发订阅服务器

.net Prism事件聚合-未触发订阅服务器,.net,wpf,prism,eventaggregator,.net,Wpf,Prism,Eventaggregator,我正在用Prism实现一个事件聚合。我有几个模块,我想让每个模块都订阅一些事件,告诉他们什么时候需要它们。我开始做一个简单的例子,在shell中同时使用subscribed和publisher。没问题。现在;当我将订阅服务器移出到我的模块时,它们不会被触发。更奇怪的是,它实际上已经工作了好几次——所有这些我都在一个断点中挂起。所以在我看来,这似乎是某种比赛条件,但我不明白为什么 假设:我不需要在任何地方设置IEventAggregator-例如,在IoC容器中注册?这是内置在Prism中的,所以

我正在用Prism实现一个事件聚合。我有几个模块,我想让每个模块都订阅一些事件,告诉他们什么时候需要它们。我开始做一个简单的例子,在shell中同时使用subscribed和publisher。没问题。现在;当我将订阅服务器移出到我的模块时,它们不会被触发。更奇怪的是,它实际上已经工作了好几次——所有这些我都在一个断点中挂起。所以在我看来,这似乎是某种比赛条件,但我不明白为什么

假设:我不需要在任何地方设置IEventAggregator-例如,在IoC容器中注册?这是内置在Prism中的,所以我只有一个事件聚合器实例,对吗

因此,问题基本上是我应该如何/在哪里/何时设置我的订户。是否有关于物品等的具体订单?在我的简化示例中,我有一个模块MyModule。引导程序将MyModule添加到目录-使其初始化:

catalog.AddModule(typeof(MyModule));
MyModule将存储聚合器,并使用它订阅MyModuleRequestEvent。它还使用菜单注册表在应用程序菜单中注册。其思想是,最终点击菜单应该触发事件,通知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 MyModule(IEventAggregator聚合器,IApplicationMenuRegistry菜单)
{
_应用程序菜单=菜单;
_聚合器=聚合器;
}
公共无效初始化()
{
var evnt=_aggregator.GetEvent();
evnt.订阅(MyModuleRequested);
_应用程序菜单注册表项(“MyModule”,evnt);
}
公共无效MyModuleRequested(布尔b)
{
MessageBox.Show(“请求MyModule”);
}
现在,我的shell中有一个按钮将发布此事件。解析时,shell将获得相同的(?)事件聚合器

public Shell(IEventAggregator aggregator)
{
    InitializeComponent();
    var evnt = aggregator.GetEvent<MyModuleRequestedEvent>();
    EventTriggerButton.Click += (s, e) => evnt.Publish(true);
}
publicshell(IEventAggregator聚合器)
{
初始化组件();
var evnt=aggregator.GetEvent();
EventTriggerButton。单击+=(s,e)=>evnt.Publish(true);
}
注:

  • 已验证事件是否已发布。在shell中添加订阅服务器也将使该订阅服务器接收事件
  • 再次;MyModule中的订阅服务器未被触发。然而,奇怪的是,这种情况已经发生了几次
  • 我不使用事件的输入。看起来你需要一些输入类型,所以我用了一个虚拟布尔。我能处理掉这个吗
      所以,我刚得到一个理论,但现在没有时间去检验它。。明天就可以了

      问题:向ModuleCalogue中添加模块会使它们保持活动状态吗?我想会的。因此,MyModule应该保持活动状态,然后在事件发布时触发

      protected override IModuleCatalog GetModuleCatalog()
      {
          var catalog = new ModuleCatalog();
          catalog.AddModule(typeof(MyModule));
          return catalog;
      }
      
      然而,如果这不能使模块保持活动状态,那么很明显,它将很难响应事件。模块对象死亡,但它没有取消订阅-因此我将在EventAggregator列表中看到订阅服务器,但订阅服务器不再存在。也;我提到它实际上偶尔会工作——如果垃圾收集器在事件触发之前没有时间取出垃圾,情况就是这样

      这听起来像是这样吗?如果是这样的话-我还没有想到一个解决方案,所以欢迎您在不同的回复线程中建议一个


      所以,;ModuleCaloge到底是什么?只是为了初始化而保留的列表,然后扔掉

      Prism事件聚合器使用弱引用链接到事件。这是为了防止事件处理程序的内存泄漏

      一旦模块初始值设定项运行完毕,它就会被处理掉,因此事件处理程序会在触发事件之前被销毁。您可以通过使用Subscribe重载来告诉Prism保留事件处理程序

      evnt.Subscribe(MyModuleRequested, true);
      

      作为一种模式,我倾向于将任何事件订阅者放在一个单独的类中,并从modules Initialize方法调用该类。这样,当模块仍被破坏时,事件保持活动状态,但分开。

      听起来好像您得到了两个EventAggregator;使用调试器为它们创建一个对象ID,以便您可以检查并让我们知道。谢谢提示!事实上,它是用于在模块中订阅和发布的同一个EventAggregator。首先进入Shell构造函数。没有“生成对象ID”。得了1分。然后点击MyModule.Initialize中的断点,并验证那里的聚合器的ID为1。另外,当点击按钮触发发布时,我看到使用的聚合器是1。完美!您的模式是有意义的——因此我将在一个单独的类中放置一个最小的事件处理程序。谢谢我也有这个问题,添加一个视图到棱镜区域会阻止我的模块被处理,我的区域注册是否有问题?您知道关于推荐模块寿命和注册视图的任何文档吗?