|
|
I'm developing a PRISM-Module (MyModule) that should list all available Modules found in the ModuleCatalog and upon user request load the selected module by using a ModuleManager.
I'm using a MefBootstrapper and MyModule has an [Import] on the IModuleManager-interface but I get an exception when MEF is trying to compose the ModuleManager. I've seen a similar issue here: http://compositewpf.codeplex.com/discussions/258960 and
it indeed seems like an issue that the IModuleInitializer not has been composed when trying to get the IModuleManager from the container.
My Question is: How can I import the IModuleManager during composition without getting an exception?
I've made a simple project to test this and the Module that should should list all available modules looks like this:
[ModuleExport(typeof(MyModule))]
public class MyModule : IModule
{
[Import]
public IModuleManager ModuleManager { get; set; }
public void Initialize()
{
}
}
and my Bootstrapper:
public class Bootstrapper : MefBootstrapper
{
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(MyModule.MyModule).Assembly));
}
protected override DependencyObject CreateShell()
{
return ServiceLocator.Current.GetInstance<Shell>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow = (Window)Shell;
Application.Current.MainWindow.Show();
}
}
The exception looks like this:
Microsoft.Practices.Prism.Modularity.ModuleInitializeException was unhandled by user code
Message=An exception occurred while initializing module 'MyModule'.
- The exception message was: GetExportedValue cannot be called before prerequisite import 'Microsoft.Practices.Prism.MefExtensions.Modularity.MefModuleManager..ctor (Parameter="moduleInitializer", ContractName="Microsoft.Practices.Prism.Modularity.IModuleInitializer")' has been set.
Check the InnerException property of the exception for more information. If the exception occurred
while creating an object in a DI container, you can exception.GetRootException() to help locate the
root cause of the problem.
Source=Microsoft.Practices.Prism
ModuleName=MyModule
StackTrace:
at Microsoft.Practices.Prism.Modularity.ModuleInitializer.HandleModuleInitializationError(ModuleInfo moduleInfo, String assemblyName, Exception exception) in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism\Modularity\ModuleInitializer.cs:line 111
at Microsoft.Practices.Prism.Modularity.ModuleInitializer.Initialize(ModuleInfo moduleInfo) in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism\Modularity\ModuleInitializer.cs:line 70
at Microsoft.Practices.Prism.Modularity.ModuleManager.InitializeModule(ModuleInfo moduleInfo) in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism\Modularity\ModuleManager.cs:line 322
at Microsoft.Practices.Prism.Modularity.ModuleManager.LoadModulesThatAreReadyForLoad() in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism\Modularity\ModuleManager.cs:line 209
at Microsoft.Practices.Prism.MefExtensions.Modularity.MefModuleManager.OnImportsSatisfied() in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism.MefExtensions\Modularity\MefModuleManager.cs:line 113
at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.NotifyImportSatisfied()
InnerException: System.InvalidOperationException
Message=GetExportedValue cannot be called before prerequisite import 'Microsoft.Practices.Prism.MefExtensions.Modularity.MefModuleManager..ctor (Parameter="moduleInitializer", ContractName="Microsoft.Practices.Prism.Modularity.IModuleInitializer")' has been set.
Source=System.ComponentModel.Composition
StackTrace:
at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.EnsureGettable()
at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.GetExportedValue(ExportDefinition definition)
at System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine engine, ComposablePart part, ExportDefinition definition)
at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportedValue(ComposablePart part, ExportDefinition export, Boolean isSharedPart)
at System.ComponentModel.Composition.Hosting.CatalogExportProvider.CatalogExport.GetExportedValueCore()
at System.ComponentModel.Composition.Primitives.Export.get_Value()
at System.ComponentModel.Composition.ReflectionModel.ImportingItem.Cast(Type type, Export export)
at System.ComponentModel.Composition.ReflectionModel.ImportingItem.CastSingleExportToImportType(Type type, Export export)
at System.ComponentModel.Composition.ReflectionModel.ImportingItem.CastExportsToSingleImportType(Export[] exports)
at System.ComponentModel.Composition.ReflectionModel.ImportingItem.CastExportsToImportType(Export[] exports)
at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.SetImport(ImportingItem item, Export[] exports)
at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.SetImport(ImportDefinition definition, IEnumerable`1 exports)
at System.ComponentModel.Composition.Hosting.ImportEngine.PartManager.TrySetImport(ImportDefinition import, IEnumerable`1 exports)
at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImportSubset(PartManager partManager, IEnumerable`1 imports, AtomicComposition atomicComposition)
at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImportsStateMachine(PartManager partManager, ComposablePart part)
at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImports(PartManager partManager, ComposablePart part, Boolean shouldTrackImports)
at System.ComponentModel.Composition.Hosting.ImportEngine.SatisfyImports(ComposablePart part)
at System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine engine, ComposablePart part, ExportDefinition definition)
at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportedValue(ComposablePart part, ExportDefinition export, Boolean isSharedPart)
at System.ComponentModel.Composition.Hosting.CatalogExportProvider.CatalogExport.GetExportedValueCore()
at System.ComponentModel.Composition.Primitives.Export.get_Value()
at System.ComponentModel.Composition.ExportServices.GetExportedValueFromLazy[T](Export export)
at System.ComponentModel.Composition.ExportServices.<>c__DisplayClass4`2.<CreateStronglyTypedExportOfTM>b__1()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at Microsoft.Practices.Prism.MefExtensions.Modularity.MefModuleInitializer.CreateModule(ModuleInfo moduleInfo) in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism.MefExtensions\Modularity\MefModuleInitializer.cs:line 117
at Microsoft.Practices.Prism.Modularity.ModuleInitializer.Initialize(ModuleInfo moduleInfo) in c:\release\WorkingDir\PrismLibraryBuild\PrismLibrary\Desktop\Prism\Modularity\ModuleInitializer.cs:line 65
InnerException:
|
|
Developer
May 3, 2012 at 5:51 PM
|
Hi,
We could verify this behavior and as mentioned before, this seems to be caused by a timing issue when composing the
IModuleInitializer composable part.
So far, we found that this exception seems to appear only with MEF
and when registering modules in Code through the AggregateCatalog
like in your case. For example when we registered the module using a Configuration File we didn't experience this behavior.
Also no error appears when importing the IModuleManager instance, e.g. from the
Shell Window (as shown in the
ModularityWithMef QuickStart) or in a view model.
Additionally, we didn't encounter this error if the modules' InitializationMode
was set to OnDemand and it was loaded after the application was initialized.
Similar to this approach we found that when adding the module's assembly after the bootstrapper process (using the
AggregateCatalog class and InitializationMode set to WhenAvailable) the error was not thrown.
Also we created a work item in the issue tracker reporting this behavior, so that the team is aware of it.
Regards,
Agustin Adami
http://blogs.southworks.net/aadami
|
|
|
|
Thanks for your answer aadami, and thanks for adding this as an issue. :)
Now this issue is pretty easy to work around (lazy loading of the IModuleManager for example) but I wanted to verify that I didn't do anything wrong on my side.
Thanks!
|
|