Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prism:EventAggregator and MEF - 2 different instances of EventAggregator

I have the following setup:

  • An Silverlight app split across xaps/modules
  • I use MEF as DI framework to connect various parts of my application.

  • I have 2 regions:

  • One (the left one) is populated with a list view (e.g. customers)

  • One (the right one) is populated with a view containing a tabcontrol with a region which I populated (according to which customer is selected) with another view containin a tab control with a region.

    The right side result: enter image description here

To populate the first level tabcontrol I am listening to the "customer changed event" - (this works great) and when I get receive the event I populate the First Level tab area with Views:

    Dim lReg As IRegion = Me.mRegionManager.Regions("FirstLevelTabReqion")
    Dim lViewID As String = CommonDefinitions.Constants.BuildFirstLevelViewName(lUniqueID)
    Dim lFirstLevelView FirstLevelView = TryCast(lReg.GetView(lRqViewID), FirstLevelView)
    If lFirstLevelView Is Nothing Then     
         lFirstLevelView = New FirstLevelView()
         Dim lRegMan1 As IRegionManager = lReg.Add(lFirstLevelView, lViewID, True)
         lFirstLevelView.SetRegionManager(lRegMan1)
         ...
    End If

Note: When creating the FirstLevelView I have to throw in a CompositionInitializer.SatisfyImports call to make sure the FirstLevelView resolves its ViewModel reference.

To get an instance of the EventsAggregator in the SecondLevel ViewModel I use:

  <ImportingConstructor()>
  Public Sub New(ByVal iEvAggregator As IEventAggregator)
          EventAggregator = iEvAggregator
          EventAggregator.GetEvent(Of DoStuffSecondLevel).Subscribe(AddressOf OnDoStuffSecondLevel, True)

   End Sub

My problem is that the EventAggregator instance I get in the second level view model is different from the EventAggregator instance in the first level so if I publish DoStuffSecondLevel on the first level it will not be caught in the second level.

Why do I get 2 different instances of the EventAggregator?
What can I do to share the same instance of the EventAggregator across the application?

Thanks in advance

like image 471
Ando Avatar asked Oct 25 '22 11:10

Ando


1 Answers

The problem is that the MefBootstrapper creates a Container but does not register it as the DEFAULT container. When SatisfyImports is called, MEF does not see any container, so it creates a new one. That is why the instances are different, because 2 different containers are being created. To solve this, simply set the Prism Container as the default container for MEF to use.

Silverlight Solution (in your bootstrapper):

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

    //Make the container the default one.
    CompositionHost.Initialize(this.Container);

    //Etc.
}

WPF (Desktop) Solution:

Currently, I can't get the Desktop solution to work. The problem is that MEF's ExportFactory<T> and ComponentInitializer are only available to Silverlight apps (Why!?). Glen Block created a library that gives access to a desktop version of the System.ComponentModel.Composition.Initialization.dll library. I attempted to use that, but it failed because in the code it is set to fail if a container already exists... again, why? I did not try using MEF2 (Codeplex preview) with this solution yet, but I'd imagine that it would work better (perhaps). The annoying part is that if you choose to use MEF2 (Codeplex) you must rebuild the Prism binaries and replace all references of the .NET 4 MEF library with the Codeplex MEF2 library. That gives Prism the ability to work with the Codeplex MEF2 library without complaining. I will try to see if doing that makes this solution viable with WPF.

like image 105
myermian Avatar answered Oct 31 '22 08:10

myermian