1
votes

I'm actually working on a project using WPF, MEF and Prism. When I start the application, I need to export a module from the container to open a configuration window before the mainwindow is shown. The code therefore is like this:

        protected override void OnStartup(StartupEventArgs e)
        {       base.OnStartup(e);
                Bootstrapper bootstrapper = new Bootstrapper();
                bootstrapper.Run();

                var window = bootstrapper.statcontainer.GetExport<Configshell>();
                var configview = bootstrapper.statcontainer.GetExport<Module.Module1.View.ConfigView>();
                window.Value.Show();
                Keyboard.Focus(configview.Value.ok_button); }

Where bootstrapper.statcontainer is a public CompositeContainer (allocated with the "Maincontainer" of the MEFBootstrapper in CreateContainer-Method). I use it to export modules at startup. Now at GetExport() I get the following first chance exception thrown:

GetExportedValue cannot be called before prerequisite import 'MyApp.Module.Module2.ViewModels.Module2_Functions..ctor (Parameter="C_Aggregator", ContractName="Microsoft.Practices.Prism.PubSubEvents.IEventAggregator")' has been set.

And this is how the ctor there looks like:

    [Import]
    public IEventAggregator Configaggregator;

    [ImportingConstructor]
    public Module2_Functions(IEventAggregator C_Aggregator)
    {
        this.Configaggregator = C_Aggregator;
        Configaggregator.GetEvent<FromConfigWindow>();
        FromConfigWindow.Instance.Subscribe(receiveStatusFromConfigWindow);
        Configaggregator.GetEvent<ToConfigWindow>();
    }

I'am using the EventAggregator to publish the configuration and have the same ctor in another module. The confusing thing is that it worked that way until I added another completely independent import to that ViewModel. Here is how the ctor of the ConfigwindowViewModel looks like:

    [ImportingConstructor]
    public ConfigVM(IEventAggregator C_aggregator)
    {
        this.Configaggregator = C_aggregator;
        Configaggregator.GetEvent<ToConfigWindow>();
        ToConfigWindow.Instance.Subscribe(actualizeCompStatus);
        Configaggregator.GetEvent<FromConfigWindow>();
    }

    [Import]
    public IEventAggregator Configaggregator;

The two events are looking like this and both already worked until 2 days ago ;-)

[Export]
public class FromConfigWindow : PubSubEvent<Int16> 
{
    private static readonly EventAggregator _eventAggregator;
    private static readonly FromConfigWindow _event;

    static FromConfigWindow()
    {
        _eventAggregator = new EventAggregator();
        _event = _eventAggregator.GetEvent<FromConfigWindow>();
    }

    public static FromConfigWindow Instance
    {
        get { return _event; }
    }
}
[Export]
public class ToConfigWindow : PubSubEvent<Int16>
{
    private static readonly EventAggregator _eventAggregator;
    private static readonly ToConfigWindow _event;

    static ToConfigWindow()
    {
        _eventAggregator = new EventAggregator();
        _event = _eventAggregator.GetEvent<ToConfigWindow>();
    }

    public static ToConfigWindow Instance
    {
        get { return _event; }
    }
}

So finally the Problem looks to me like the EventAggregator doesn't get instanciated and therefore the exception gets thrown. But how can I work around this? Or am I doing something wrong in the linkage of the Aggregator in the constructors?

I already tried to modify all constructor arguments with an [Import] attribute, this threw the same exception as well, or removing all [Import] attributes form the IEventAggregator Configaggregator objects in the ViewModels.

The problem is similar to this link here but in my case happens with the EventAggregator from the Prism framework.

Please tell me if I should provide you more parts of the code.

2

2 Answers

1
votes

I'm not sure why you're Exporting your PubSubEvents or holding a reference to a static new EventAggregator in them. You should only be using one instance of EventAggregator (in this example) which you'll get from your container (Prism will put it there for you).

You should go back to basics and read the excellent Prism documentation. Section 9 "Communicating Between Loosely Coupled Components" for an overview of EventAggregator and PubSubEvents.

If you want to create a bare bones project which simulates the problem you're having and upload it somewhere, I'll gladly have a look at it for you.

1
votes

It looks like the error is because you have not satisfied all your imports before beginning operations on them. I concur with ChrisO, you should go back and check out the docs. There are a lot of things going on here which seem to be overcomplicating things. Why is there a new EventAggregator() in there? MEF should import that dependency for you. Why all the messing around with the container and getting exports? It seems you are doing a lot of work that should be taken care of by MEF and Prism.