Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prism event aggregator not working from separate module

Tags:

c#

events

wpf

prism

I am having trouble with the prism event aggregator. If I subscribe to, and publish an event in the same module it works fine. Like this -

public class InfrastructureModule : IModule
{
    private IEventAggregator eventAggregator;

    public InfrastructureModule(IEventAggregator eventAggregator)
    {
        this.eventAggregator = eventAggregator;
        eventAggregator.GetEvent<TestEvent>().Subscribe(TestSub);
    }

    public void Initialize()
    {
        eventAggregator.GetEvent<TestEvent>().Publish("Infrastructure module");
    }

    private void TestSub(string s)
    {
        MessageBox.Show(s);
    }
}

However if I subscribe to the event in another module nothing happens when eventAggregator.GetEvent().Publish() is called -

public class OtherModule : IModule
{
    private IEventAggregator eventAggregator;

    public OtherModule (IEventAggregator eventAggregator)
    {
        this.eventAggregator = eventAggregator;
    }

    public void Initialize()
    {
        eventAggregator.GetEvent<TestEvent>().Publish("Other module");
    }
}

The Infrastructure module is registered first so the problem is not that OtherModule is publishing an event before there is a subscriber. Any ideas whats going wrong?

Edit: Here is where I am registering the modules

class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return new Shell();
    }

    protected override void InitializeShell()
    {
        base.InitializeShell();

        App.Current.MainWindow = (Window)this.Shell;
        App.Current.MainWindow.Show();
    }

    protected override void ConfigureModuleCatalog()
    {
        base.ConfigureModuleCatalog();

        ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;

        // Infrastructure module
        moduleCatalog.AddModule(typeof(Infrastructure.InfrastructureModule));


        moduleCatalog.AddModule(typeof(Other.OtherModule));
    }
}
like image 628
Jim_CS Avatar asked Dec 28 '11 16:12

Jim_CS


1 Answers

Based on the comments of the OP, the objects are instantiated then destroyed right after.
This makes the Publish("OtherModule"); code do nothing, because the listener was destroyed.

Now indeed, if you set KeepSubscriberReferenceAlive to true,
it will work because your EventAggregator will keep a reference to the subscriber object (InfrastructureModule).
That is not ideal, basically you went from using a Weak Event Pattern where you don't risk memory leaks,
to having to handle objects lifetime and thus risk memory leaks just like a regular .NET event.

Don't get me wrong, I'm not saying you absolutely shouldn't use KeepSubscriberReferenceAlive, but it should only be used on rare occasions.

That being said, your test case is an odd scenario: the Bootstrapper will call Initialize on every Module you define, and then your shell does not hold those modules. Since nobody holds those Modules, they're destroyed.

The "normal" usage for Initialize, is to inject the module that is being initialized into the Shell (or any other UserControl), and it makes sense: you don't want to initialize something you will not use.

like image 158
Louis Kottmann Avatar answered Sep 21 '22 17:09

Louis Kottmann