【问题标题】:IEventAggregator does not reach accross modulesEventAggregator 无法跨模块访问
【发布时间】:2010-11-15 03:51:32
【问题描述】:

我试图让我的 IEventAggregator 允许我在一个模块中发布和事件并在另一个模块中捕获它。我在一个模块/项目中尝试了下面的代码,效果很好。只有当我有一个模块/项目发布事件而另一个订阅它时,它才会失败。

我已通过统一将 IEventAggregator 注入到两个模块中。

我有 3 个项目,其中两个有模块(称为 A 和 B),一个只是一个普通的类库(称为接口)

在类库Interfaces中有这样的代码:

public class RandomTestEvent : CompositePresentationEvent<string>
{
}

在模块A中有一个按钮点击命令中的代码(这实际上是在项目的视图模型中):

var evt2 = _eventAggregator.GetEvent<RandomTestEvent>();
evt2.Publish("Testing");

在模块B中有这样的代码:

    public void Initialize()
    {
        var evt2 = _eventAggregator.GetEvent<RandomTestEvent>();
        evt2.Subscribe(OnRandomThingDone);
    }

    private void OnRandomThingDone(string obj)
    {
        MessageBox.Show("Random Event Done With: " + obj);            
    }

我可以追踪并看到订阅被调用。当我看到 Publish 被调用时,调试器说 Subscriptions = 1(所以它知道订阅已完成,所以我似乎没有 2 个不同的 IEventAggregator 实例。)

但 OnRandomThingDone 在 Publish 之后永远不会被调用。

任何想法为什么? (我需要发布更多代码吗?如果需要,请告诉我。)

【问题讨论】:

  • 订阅 SAME 模块中的事件,看看你的代码是否被调用。这会告诉你问题出在哪个模块。

标签: c# wpf unity-container prism eventaggregator


【解决方案1】:

真的是随机猜测 - 您的订阅者在事件发布之前得到 GC - 因为 Prism 的 CompositePresentationEvent 的默认行为是使用 Wea​​kReferences 来保留订阅者目标引用。

所以...尝试调用 Subscribe 重载,它允许您指定 keepSubscriberReferenceAlive 并传入 true。

如果您的订阅者随后成功接收到事件,则意味着您的包含 OnRandomThingDone 的类超出范围并在事件发布之前获得 GC。

随机 API 参考: http://msdn.microsoft.com/en-us/library/ff921122(PandP.20).aspx

【讨论】:

  • 你太棒了!就是这样!谢谢!
  • 您的订阅者被 GC'd 的原因是它是模块类的一部分,仅在 Prism 引导时才存在。通过在 subscribe 中传递 true ,您可以强制事件订阅使模块保持活动状态。更好的选择可能是订阅组件中的事件,该组件使用 ContainerControlledLifetime 向 unityconainer 注册
【解决方案2】:

其实grimcoder是对的,弱引用需要公共Action方法。 使用周引用可以减轻编码人员退订事件的负担,这由 GC 管理。

但是,您可以通过将 true 传递给 keepSubscriberReferenceAlive 来使用强引用,如果在短时间内调用大量事件,这也可以加快您的程序。

有关这方面的更多信息,请参阅:Chapter 9: Communicating Between Loosely Coupled Components 部分 使用强引用订阅

【讨论】:

    【解决方案3】:

    它与 GC 无关,因为一旦 Subsriber 附加了对它的引用,它就永远不会消失。 真正的问题是由于无法访问OnRandomThingDone 如果必须是 public 即:

    **public** void OnRandomThingDone(string obj)
    {
        MessageBox.Show("Random Event Done With: " + obj);            
    }
    

    【讨论】:

    • 其实,没有。 @JeffN825 是正确的;订阅者被保留为弱参考。虽然 Vaccano 的代码没有显示它,但 Subscribe 方法实际上为该方法提供了一个 Action,这意味着该方法不必是公共的。所以你的帖子是错误的。
    猜你喜欢
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多