protected override IUnityContainer CreateContainer() { LoggerFacade.Log(@"Creating the Unity Dependency Injection container and binding (bi-directionally) with the default MEF composition catalog (i.e. Tobi.exe, for the empty shell window)", Category.Debug, Priority.Low); // MEF will scan Tobi.exe only to start with, // so that the shell window doesn't attempt to load dependencies immediately but in a differed manner // (through a container re-composition when we add further MEF discovery catalogs) var aggregateCatalog = new AggregateCatalog(new ComposablePartCatalog[] { new AssemblyCatalog(Assembly.GetExecutingAssembly()), //new AssemblyCatalog(this.GetType().Assembly), //new AssemblyCatalog(typeof(Shell).Assembly), //new TypeCatalog(typeof(typeX)) //new TypeCatalog(typeof(type1), typeof(type2), ...) }); // This instance, once returned to this method, will be available as the "Container" class member (property), // and it will be registered within the Unity dependency injection container itself. var unityContainer = new UnityContainer(); // Bidirectional binding between MEF and Unity. // Remark: calls MEF-Compose, which triggers application Parts scanning // (building the graph of dependencies, and pruning branches that are rejected), // but the OnImportsSatisfied callbacks will only be activated at instanciation time. MefContainer = unityContainer.RegisterFallbackCatalog(aggregateCatalog); return(unityContainer); }
/// <summary> /// The shell is loaded at this stage, so we load the rest of the application /// by discovering plugins and the extension points they fulfill, /// and by resolving instances through the MEF dependency graph. /// </summary> protected override void InitializeModules() { // Does nothing, as we do not use any real CAG IModule (only the dummy empty one). base.InitializeModules(); var shell = Container.TryResolve <IShellView>(); DebugFix.Assert(shell != null); // MEF will fetch DLL assemblies adjacent to the Tobi.exe executable // We could add support for a special "plugin" folder, // using something like: + Path.DirectorySeparatorChar + "addons"; string mefDir = AppDomain.CurrentDomain.BaseDirectory; // sowe can call dirCatalog.Refresh(); when needed (which triggers re-composition) //var dirCatalog = new DirectoryCatalog(mefDir, @"Tobi.Plugin.*.dll"); //Container.RegisterCatalog(dirCatalog); // Any MEF part exported from this directory will take precedence over the built-in Tobi ones. // As a result, a single Import (as opposed to ImportMany) that has several realizations // (i.e. the default/fallback Tobi implementation and the custom Extension) // will not trigger an exception (as it is normally the case), instead the Extension will be returned, and the built-in feature ignored. var directories = Directory.GetDirectories(mefDir, @"Extensions", SearchOption.TopDirectoryOnly); // @"*.*" foreach (var directory in directories) { try { // We use the direct loading below to avoid UNC network drives issues. //Container.RegisterCatalog(new DirectoryCatalog(directory)); var extensionsAggregateCatalog = new AggregateCatalog(); foreach (string file in Directory.GetFiles(directory, "*.dll")) { var assembly = Assembly.LoadFrom(file); extensionsAggregateCatalog.Catalogs.Add(new AssemblyCatalog(assembly)); } Container.RegisterCatalog(extensionsAggregateCatalog); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } } //var dirCatalog = new DirectoryCatalog(mefDir, @"Tobi.Plugin.MenuBarDebug*.dll"); //Container.RegisterCatalog(dirCatalog); var tobiModulesExtensions = MefContainer.GetExportedValues <ITobiPlugin>(); foreach (var tobiModuleEXT in tobiModulesExtensions) { DebugFix.Assert(!string.IsNullOrEmpty(tobiModuleEXT.Name) && !string.IsNullOrEmpty(tobiModuleEXT.Description)); LoggerFacade.Log(@"Loaded extension plugin: [[" + tobiModuleEXT.Name + @"]] [[" + tobiModuleEXT.Description + @"]]", Category.Debug, Priority.Low); } // NOTE: we're loading assemblies manually so that they get picked-up by ClickOnce deployment (and it means we can control the order of registration). try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(UrakawaPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(AbstractTobiPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(AudioPanePlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(ValidatorPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(MetadataValidatorPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(ContentDocumentValidatorPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(MissingAudioValidatorPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(MetadataPanePlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(StructureTrailPanePlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(DocumentPanePlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AggregateCatalog(new ComposablePartCatalog[] { //new AssemblyCatalog(Assembly.GetAssembly(typeof(HeadingNavigationPlugin))), // in the same assembly as the main Navigation Plugin, so not needed //new AssemblyCatalog(Assembly.GetAssembly(typeof(PageNavigationPlugin))), // in the same assembly as the main Navigation Plugin, so not needed //new AssemblyCatalog(Assembly.GetAssembly(typeof(MarkersNavigationPlugin))), // in the same assembly as the main Navigation Plugin, so not needed new AssemblyCatalog(Assembly.GetAssembly(typeof(NavigationPanePlugin))) })); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { //new AssemblyCatalog(Assembly.GetAssembly(typeof(DescriptionsNavigationPlugin))), // in the same assembly as the main Navigation Plugin, so not needed Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(DescriptionsPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } //MessageBox.Show(@"Urakawa session should now be resolved (window title changed)"); var tobiModules = MefContainer.GetExportedValues <ITobiPlugin>(); foreach (var tobiModule in tobiModules) { DebugFix.Assert(!string.IsNullOrEmpty(tobiModule.Name) && !string.IsNullOrEmpty(tobiModule.Description)); LoggerFacade.Log( @"Loaded plugin: [[" + tobiModule.Name + @"]] [[" + tobiModule.Version + @"]] [[" + tobiModule.Description + @"]]", Category.Debug, Priority.Low); } //MessageBox.Show(@"Urakawa module is loaded but it 'waits' for a toolbar to push its commands: press ok to get the toolbar view to load (but not to display yet)"); // This artificially emulates the dynamic loading of the Toolbar and Menubar plugin: // the container gets composed again and the modules dependent on the toolbar/menubar gets satisified try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(ToolBarsPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(MenuBarPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } try { Container.RegisterFallbackCatalog(new AssemblyCatalog(Assembly.GetAssembly(typeof(SettingsPlugin)))); } catch (Exception ex) { ExceptionHandler.Handle(ex, false, shell); } //MessageBox.Show(@"After pressing ok the toolbar module will load to integrate the view into the window"); var tobiModulesAFTER = MefContainer.GetExportedValues <ITobiPlugin>(); foreach (var tobiModuleAFTER in tobiModulesAFTER) { DebugFix.Assert(!string.IsNullOrEmpty(tobiModuleAFTER.Name) && !string.IsNullOrEmpty(tobiModuleAFTER.Description)); LoggerFacade.Log(@"Loaded plugin AFTER: [[" + tobiModuleAFTER.Name + @"]] [[" + tobiModuleAFTER.Description + @"]]", Category.Debug, Priority.Low); } // In ClickOnce application manifest: //<fileAssociation xmlns="urn:schemas-microsoft-com:clickonce.v1" extension=".text" description="Text Document (ClickOnce)" progid="Text.Document" defaultIcon="text.ico" /> // // Arguments for ClickOnce-actived application are passed here (including file path due to file extension association): //string[] args = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData; //if (args != null && args.Length != 0) //{ // try // { // Uri uri = new Uri(args[0]); // if (!uri.IsFile) // throw new UriFormatException("The URI " + uri + " is not a file."); // OpenFile(uri.AbsolutePath); // } // catch (UriFormatException) // { // MessageBox.Show("Invalid file specified.", Program.Name); // } //} // The code below is totally obsolete, as we are not using CAG modules. //var name = typeof (UrakawaModule).Name; //var moduleCatalog = Container.Resolve<IModuleCatalog>(); //foreach (var module in moduleCatalog.Modules) //{ // if (module.ModuleName == name) // { // var moduleManager = Container.Resolve<IModuleManager>(); // moduleManager.LoadModule(module.ModuleName); // } //} usageReport(shell); }
public override bool PersistInHistory() { LoggerFacade.Log(String.Join(" ", DateTime.Now.ToString(), this.GetType().Name, System.Reflection.MethodBase.GetCurrentMethod().Name), Category.Debug, Priority.None); return(base.PersistInHistory()); }
public override void OnNavigatedTo(NavigationContext navigationContext) { LoggerFacade.Log(String.Join(" ", DateTime.Now.ToString(), this.GetType().Name, System.Reflection.MethodBase.GetCurrentMethod().Name), Category.Debug, Priority.None); base.OnNavigatedTo(navigationContext); }
public override bool IsNavigationTarget(NavigationContext navigationContext) { LoggerFacade.Log(String.Join(" ", DateTime.Now.ToString(), this.GetType().Name, System.Reflection.MethodBase.GetCurrentMethod().Name), Category.Debug, Priority.None); return(base.IsNavigationTarget(navigationContext)); }
public override void ConfirmNavigationRequest(NavigationContext navigationContext, Action <bool> continuationCallback) { LoggerFacade.Log(String.Join(" ", DateTime.Now.ToString(), this.GetType().Name, System.Reflection.MethodBase.GetCurrentMethod().Name), Category.Debug, Priority.None); base.ConfirmNavigationRequest(navigationContext, continuationCallback); }