GetExportedValue cannot be called...

Topics: Bootstrappers & IoC, Getting Started
Jul 21, 2011 at 10:27 PM

I get the following exception when trying to import (inject) the shell in another view model:

GetExportedValue cannot be called before prerequisite import 'LF.WI.MPO.Shell.ViewModels.ShellViewModel..ctor (Parameter="windowManager", ContractName="Caliburn.Micro.IWindowManager")' has been set.

The classes look like this:

[Export(typeof(IShell))]
 public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShell, IPartImportsSatisfiedNotification, IHandle<IUser>, IHandle<FooterContent>
   {
      [ImportingConstructor]
      public ShellViewModel( IWindowManager windowManager, IEventAggregator aggregator )
      {
		  _windowManager = windowManager;
         _aggregator = aggregator;
      }
...
[Export( typeof( LoginViewModel ) )]
public class LoginViewModel : Screen
   {
      [ImportingConstructor]
      public LoginViewModel( IWindowManager windowManager, IEventAggregator aggregator  )
      {
		  _windowManager = windowManager;
         _aggregator = aggregator;
      }

	  [Import(typeof(IShell))]
	  public IShell Shell { get; set; }
...
 protected override void Configure()
      {
         var catalog = new AggregateCatalog(
             SelectAssemblies().Select( x => new AssemblyCatalog( x ) ).OfType<ComposablePartCatalog>()
         );
         container = CompositionHost.Initialize( catalog );

         var batch = new CompositionBatch();

         batch.AddExportedValue<IWindowManager>( new WindowManager() );
         batch.AddExportedValue<IEventAggregator>( new EventAggregator() );

         batch.AddExportedValue( container );
         batch.AddExportedValue( catalog );

         container.Compose( batch );

...

Whenever trying to import/inject the shell in another view model I get the above exception. What am I doing wrong?

In the shell view model I do a lazy ImportMany:

 [ImportMany( typeof( IMainModule ) )]
      public IEnumerable<Lazy<IMainModule, IMainModuleMetadata>> MainModules { get; set; }

which I finally activate in 

 public void OnImportsSatisfied()
      {
         ActivateMainModule( ApplicationSettings.AppState.LoggedOut );
      }
...

private void ActivateMainModule( ApplicationSettings.AppState appState )
      {
		  ActiveMainModule = MainModules.FirstOrDefault(m => m.Metadata.AppState == appState);
		  if (ActiveMainModule != null)
			  ActivateItem(ActiveMainModule.Value);
      }

Can this probably be a problem?

Please let me know what's wrong or just tell me other ways to get a reference to the shell from within other view models.

Jul 22, 2011 at 10:46 PM

It seems an issue with MEF having problems to construct an instance of ShellViewModel. It's hard to tell (and sometimes tricky to track down, in my experience).
Unfortunately I'm not a MEF expert, so I digged around a bit on the web; that particular exception seems frequently related to circular references or to threading issue.

The way you are getting an IShell instance seems fine to me; if you can't get a better advice, I would try to remove the modules collection to check if it prevents the creation of a shell instance.