/// <summary> /// Initializes the modules, imports all the types that are exported from the plugins and passes them to the <see cref="MainWindowViewModel"/> /// </summary> protected override void InitializeModules() { try { base.InitializeModules(); } catch (ModularityException e) { //Error during initialization of some plugin //Be verbose so that the user could spot the broken plugin and remove it, for example .. var dialogService = Container.Resolve <IDialogService>(); var dialogParams = new DialogParameters { { MessageDialogParameterNames.Message, e.Message }, { MessageDialogParameterNames.Title, "Error" } }; dialogService.ShowDialog("MessageDialogView", dialogParams, (dialogResult) => { }); } if (!loadedPlugins.Any(x => x.Assembly.FullName.StartsWith("PaunPacker.Plugins.DefaultImplementationsProviderPlugin,", StringComparison.InvariantCulture))) { //The default implementations plugin was not loaded var dialogService = Container.Resolve <IDialogService>(); var dialogParams = new DialogParameters { { MessageDialogParameterNames.Message, "Critical error was encountered, the PaunPacker could no run without the plugin with default implementations !" }, { MessageDialogParameterNames.Title, "Error" } }; dialogService.ShowDialog("MessageDialogView", dialogParams, (dialogResult) => { }); Shutdown(-1); } //Assign modules to Shell's ViewModel properly .. var mainWindowVM = (MainWindowViewModel)MainWindow.DataContext; //Get All instances from mefContainer //The reason why only mefContainer is considered here is because unityContainer should be used mainly for //factoryRegistrations and dependencies used by these factories are not registered yet //On the other hand, MEF is used for easy&fast way to export dependency-less plugins so it is safe to instantiate them at any moment var imageSorters = mefContainer.GetExports <IImageSorter>(); var placementAlgorithms = mefContainer.GetExports <IPlacementAlgorithm>(); var minimumBoundingBoxFinders = mefContainer.GetExports <IMinimumBoundingBoxFinder>(); var metadataWriters = mefContainer.GetExports <IMetadataWriter>(); var imageProcessors = mefContainer.GetExports <IImageProcessor>(); //Get All exported types (from both mefContainer & unityContainer) var imageSorterTypes = imageSorters.Select(x => x.GetType()) .Concat(FilterUnityExportedTypesByTypeAndAttribute <IImageSorter>(UnityContainer)); var placementAlgorithmTypes = placementAlgorithms.Select(x => x.GetType()) .Concat(FilterUnityExportedTypesByTypeAndAttribute <IPlacementAlgorithm>(UnityContainer)); var minimumBoundingBoxFinderTypes = minimumBoundingBoxFinders.Select(x => x.GetType()) .Concat(FilterUnityExportedTypesByTypeAndAttribute <IMinimumBoundingBoxFinder>(UnityContainer)); var metadataWriterTypes = metadataWriters.Select(x => x.GetType()) .Concat(FilterUnityExportedTypesByTypeAndAttribute <IMetadataWriter>(UnityContainer)); var imageProcessorTypes = imageProcessors.Select(x => x.GetType()) .Concat(FilterUnityExportedTypesByTypeAndAttribute <IImageProcessor>(UnityContainer)); mainWindowVM.LoadedPlugins = loadedPlugins .Concat(mefContainer.GetExports <IMetadataWriter>().Select(x => x.GetType())) .Concat(mefContainer.GetExports <IImageProcessor>().Select(x => x.GetType())) .Concat(mefContainer.GetExports <IImageSorter>().Select(x => x.GetType())) .Concat(mefContainer.GetExports <IPlacementAlgorithm>().Select(x => x.GetType())) .Concat(mefContainer.GetExports <IMinimumBoundingBoxFinder>().Select(x => x.GetType())) .Distinct(); //ExportedTypeMetadataAttribute can be either placed directly on the exported type or on the Plugin Entry point type //Obtain all the ExportedTypeMetadataAttributes that are on the Plugin entry points instead of on the actual class being exported var exportedMetadataAttributesOnPlugins = mainWindowVM.LoadedPlugins .Select(x => x.GetCustomAttributes <ExportedTypeMetadataAttribute>()); var exportedTypeNameToExportedTypeAttributeMapping = new Dictionary <string, ExportedTypeMetadataAttribute>(); foreach (var plugin in exportedMetadataAttributesOnPlugins) { foreach (var exportedType in plugin) { exportedTypeNameToExportedTypeAttributeMapping[exportedType.ExportedType.FullName] = exportedType; } } mainWindowVM.ImageSorterVMs = imageSorterTypes .Distinct() .Select(x => CreateExportedTypeViewModel(x, exportedTypeNameToExportedTypeAttributeMapping)); mainWindowVM.PlacementAlgorithmVMs = placementAlgorithmTypes .Distinct() .Select(x => CreateExportedTypeViewModel(x, exportedTypeNameToExportedTypeAttributeMapping)); mainWindowVM.MinimumBoundingBoxFinderVMs = minimumBoundingBoxFinderTypes .Distinct() .Select(x => CreateExportedTypeViewModel(x, exportedTypeNameToExportedTypeAttributeMapping)); mainWindowVM.MetadataWriterVMs = metadataWriterTypes .Distinct() .Select(x => CreateExportedTypeViewModel(x, exportedTypeNameToExportedTypeAttributeMapping)); mainWindowVM.ImageProcessorVMs = imageProcessorTypes .Distinct() .Select(x => CreateExportedTypeViewModel(x, exportedTypeNameToExportedTypeAttributeMapping)); //The event about modules being loaded is published before view manipulation (because modules could register view in event handler of the modules loaded event) var eventAggregator = UnityContainer.Resolve <IEventAggregator>(); eventAggregator.GetEvent <ModulesLoadedEvent>().Publish(new ModulesLoadedPayload( imageSorterTypes .Concat(placementAlgorithmTypes) .Concat(minimumBoundingBoxFinderTypes) .Concat(metadataWriterTypes) .Concat(imageProcessorTypes) )); var regionManager = Container.Resolve <IRegionManager>(); //Get views for ImageSorters var collection = regionManager.Regions[RegionNames.ImageSortersRegion]; foreach (var imageSorter in mainWindowVM.ImageSorterVMs) { var view = UnityContainer.Resolve <System.Windows.Controls.UserControl>(PluginViewWiring.GetViewName(imageSorter.ExportedType)); if (view != null) { regionManager.Regions[RegionNames.ImageSortersRegion].Add(view, PluginViewWiring.GetViewName(imageSorter.ExportedType)); collection.Deactivate(view); } } //Get views for PlacementAlgorithms, register them and hide all of them collection = regionManager.Regions[RegionNames.PlacementAlgorithmsRegion]; foreach (var placementAlgorithm in mainWindowVM.PlacementAlgorithmVMs) { var view = UnityContainer.Resolve <System.Windows.Controls.UserControl>(PluginViewWiring.GetViewName(placementAlgorithm.ExportedType)); if (view != null) { regionManager.Regions[RegionNames.PlacementAlgorithmsRegion].Add(view, PluginViewWiring.GetViewName(placementAlgorithm.ExportedType)); collection.Deactivate(view); } } //Get views for MinimumBoundingBoxFinders collection = regionManager.Regions[RegionNames.MinimumBoundingBoxFinderRegion]; foreach (var minBoundingBoxFinder in mainWindowVM.MinimumBoundingBoxFinderVMs) { var view = UnityContainer.Resolve <System.Windows.Controls.UserControl>(PluginViewWiring.GetViewName(minBoundingBoxFinder.ExportedType)); if (view != null) { regionManager.Regions[RegionNames.MinimumBoundingBoxFinderRegion].Add(view, PluginViewWiring.GetViewName(minBoundingBoxFinder.ExportedType)); collection.Deactivate(view); } } //Get views for MetadataWriters collection = regionManager.Regions[RegionNames.MetadataWritersRegion]; foreach (var metadataWriter in mainWindowVM.MetadataWriterVMs) { var view = UnityContainer.Resolve <System.Windows.Controls.UserControl>(PluginViewWiring.GetViewName(metadataWriter.ExportedType)); if (view != null) { regionManager.Regions[RegionNames.MetadataWritersRegion].Add(view, PluginViewWiring.GetViewName(metadataWriter.ExportedType)); collection.Deactivate(view); } } //Get views for ImageProcessors collection = regionManager.Regions[RegionNames.ImageProcessorsRegion]; foreach (var imageProcessor in mainWindowVM.ImageProcessorVMs) { var view = UnityContainer.Resolve <System.Windows.Controls.UserControl>(PluginViewWiring.GetViewName(imageProcessor.ExportedType)); if (view != null) { regionManager.Regions[RegionNames.ImageProcessorsRegion].Add(view, PluginViewWiring.GetViewName(imageProcessor.ExportedType)); collection.Deactivate(view); } } mainWindowVM.Initialize(); }