Question

I am running the latest PRISM 4.2. Unfortunately the Event Aggregator tutorial in the documentation is driven via Unity instead of MEF. And I can't get it running under MEF.

App.xaml.cs

 public partial class App : Application
    {
        [Import]
        public IEventAggregator eventAggregator;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            Bootstrapper bootstrapper = new Bootstrapper();
            bootstrapper.Run();
        }
    }

Bootstrapper.cs

public class Bootstrapper : MefBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            return new MainWindow();
        }

        protected override void InitializeShell()
        {
            base.InitializeShell();
            App.Current.MainWindow = (Window)Shell;
            App.Current.MainWindow.Show();
        }

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

            AggregateCatalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));
        }

        protected override IModuleCatalog CreateModuleCatalog()
        {
            ModuleCatalog moduleCatalog = new ModuleCatalog();

            return moduleCatalog;
        }

    }

MainWindow.xaml.cs

public partial class MainWindow : Window, IView
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
        }
    }

MainViewModel.cs:

[ModuleExport(typeof(MainViewModel))]
    public class MainViewModel : BindableBase, IServiceCallback
    {
        [Import]
        public IEventAggregator eventAggregator;

        [ImportingConstructor]
        public MainViewModel()
        {            
            eventAggregator.GetEvent<AppExitEvent>().Publish("");

        }
     }

Despite the [import] the event aggregator is always null both in App.xaml.cs and in MainViewModel. Why is that?
The second question is do I have to export my Viewmodels as a module (as I did above) to use an even aggregator inside them?

UPDATE:

Proof that latest version of PRISM doesn't support ComposeExportedValue anymore.

enter image description here

'System.ComponentModel.Composition.Hosting.CompositionContainer' does not contain a definition for 'ComposeExportedValue' and no extension method ...

Was it helpful?

Solution

The solution to this would be what SchubertJ replied on your same question at CodePlex:

As a deeper analyisis, the Import attribute on Properties would not be resolved until the constructor finishes. That is why you would need to inject the EventAggregator dependency through the constructor as a parameter if this dependency would be used on the constructor implementation.

Therefore, if you would like to use the EventAggregator dependency on the ViewModel constructor, you should use [ImportConstructor] attribute instead, and ask the container for the EventAggregator instance by retreiving it as a parameter:

public class MainViewModel
{
    private readonly IEventAggregator eventAggregator;

    [ImportingConstructor]
    public MainViewModel(IEventAggregator eventAggregator)
    {
       this.eventAggregator = eventAggregator;

       this.eventAggregator.GetEvent<MyEvent>().Publish("");
    }
}

You may find more related information regarding both import alternatives in the following post:

I hope this helped you, Regards.

OTHER TIPS

In your bootstrapper class have this method :

protected override void ConfigureContainer()
{
     base.ConfigureContainer();
     Container.ComposeExportedValue(new EventAggregator());
}

You should look at this article as it is answer both your first and second question in better details. http://www.gonetdotnet.info/posts/wpf-articles/wpf-module-communication

Update:

If you create a class as below it will match your export with your import.

public class EventAggProvider
   {
     [Export(typeof(IEventAggregator))]
     public IEventAggregator eventAggregator { get { return new EventAggregator(); } }
   }

It is a little late, but there is also a solution for the case in which you want the EventAggregator gets injected in property. Implement 'IPartImportsSatisfiedNotification' and use the eventaggregator in 'OnImportsSatisfied' method.

public class MainViewModel : BindableBase,  IPartImportsSatisfiedNotification
{
    [Import]
    public IEventAggregator eventAggregator;

    public void OnImportsSatisfied()
    {
        eventAggregator.GetEvent<AppExitEvent>().Publish("");
    }
 }

EventAggregator does not depend on MEF or Unity it's design pattern coined by Martin Fowler and it's based on publisher subscriber scenario

try to follow this steps

//this should be in your infrastructure layer

public  static class EventAggregatorHelper
{
  private static IEventAggregator _Current = new EventAggregator();
  public static IEventAggregator Current
  {
    get
    {
      return _Current;
    }
  }
}



The HandleAppExitEvent is a class declared as shown below:

public class AppExitEvent : CompositePresentationEvent<String>
{
} 

and the subscriber would be something like this:

in your MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();  
 //In this case the HandleAppExitEvent and the subscriber that deals with this event.                   
 EventAggregatorHelper.Current.GetEvent<AppExitEvent>().   Subscribe(HandleAppExitEvent);  

            }
      //note that this method should be public 

 public void HandleAppExitEvent(string mess)
    {
       if (!String.IsNullOrEmpty(mess))
       {
          //Do whatever you need to do here.
       }
    }

    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top