private void ConfigureContainer(IProgress <string> progress) { kernel.Bind <ICommandLineArgs>().ToConstant(commandLineArgs).InSingletonScope(); // use single logger for whole application kernel.Bind <Logger>().ToSelf().InSingletonScope(); kernel.Get <Logger>(); Debug.WriteLine($"Starting Astrarium {FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion}"); kernel.Bind <ISettings, Settings>().To <Settings>().InSingletonScope(); kernel.Bind <ISky, Sky>().To <Sky>().InSingletonScope(); kernel.Bind <ISkyMap, SkyMap>().To <SkyMap>().InSingletonScope(); kernel.Bind <UIElementsIntegration>().ToSelf().InSingletonScope(); UIElementsIntegration uiIntegration = kernel.Get <UIElementsIntegration>(); ICollection <AbstractPlugin> plugins = new List <AbstractPlugin>(); string homeFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); IEnumerable <string> pluginPaths = Directory.EnumerateFiles(homeFolder, "Astrarium.Plugins.*.dll", SearchOption.AllDirectories); progress.Report("Loading plugins"); foreach (string path in pluginPaths) { try { var plugin = Assembly.UnsafeLoadFrom(path); Debug.WriteLine($"Loaded plugin {plugin.FullName}"); } catch (Exception ex) { Trace.TraceError($"Unable to load plugin assembly with path {path}. {ex})"); } } // collect all plugins implementations Type[] pluginTypes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .Where(t => typeof(AbstractPlugin).IsAssignableFrom(t) && !t.IsAbstract) .ToArray(); // collect all calculators types Type[] calcTypes = pluginTypes .SelectMany(p => GetCalculators(p)) .ToArray(); foreach (Type calcType in calcTypes) { var types = new[] { calcType }.Concat(calcType.GetInterfaces()).ToArray(); kernel.Bind(types).To(calcType).InSingletonScope(); } // collect all renderers types Type[] rendererTypes = pluginTypes .SelectMany(p => GetRenderers(p)) .ToArray(); foreach (Type rendererType in rendererTypes) { var types = new[] { rendererType }.Concat(rendererType.GetInterfaces()).ToArray(); kernel.Bind(rendererType).ToSelf().InSingletonScope(); } // collect all event provider implementations Type[] eventProviderTypes = pluginTypes .SelectMany(p => GetAstroEventProviders(p)) .ToArray(); foreach (Type eventProviderType in eventProviderTypes) { kernel.Bind(eventProviderType).ToSelf().InSingletonScope(); } foreach (Type pluginType in pluginTypes) { progress.Report($"Creating plugin {pluginType}"); kernel.Bind(pluginType).ToSelf().InSingletonScope(); var plugin = kernel.Get(pluginType) as AbstractPlugin; // add settings configurations uiIntegration.SettingItems.AddRange(plugin.SettingItems); // add configured toolbar buttons uiIntegration.ToolbarButtons.AddRange(plugin.ToolbarItems); // add menu items uiIntegration.MenuItems.AddRange(plugin.MenuItems); plugins.Add(plugin); } // Default rendering order for BaseRenderer descendants. uiIntegration.SettingItems.Add("Rendering", new SettingItem("RenderingOrder", new RenderingOrder(), typeof(RenderersListSettingControl))); var settings = kernel.Get <ISettings>(); // set settings defaults foreach (string group in uiIntegration.SettingItems.Groups) { foreach (var item in uiIntegration.SettingItems[group]) { settings.Set(item.Name, item.DefaultValue); } } settings.Save("Defaults"); progress.Report($"Loading settings"); settings.Load(); SetLanguage(settings.Get <string>("Language")); SetColorSchema(settings.Get <ColorSchema>("Schema")); SkyContext context = new SkyContext( new Date(DateTime.Now).ToJulianEphemerisDay(), new CrdsGeographical(settings.Get <CrdsGeographical>("ObserverLocation"))); progress.Report($"Creating calculators"); var calculators = calcTypes .Select(c => kernel.Get(c)) .Cast <BaseCalc>() .ToArray(); progress.Report($"Creating event providers"); var eventProviders = eventProviderTypes .Select(c => kernel.Get(c)) .Cast <BaseAstroEventsProvider>() .ToArray(); progress.Report($"Creating renderers"); var renderers = rendererTypes.Select(r => kernel.Get(r)).Cast <BaseRenderer>().ToArray(); kernel.Get <Sky>().Initialize(context, calculators, eventProviders); kernel.Get <SkyMap>().Initialize(context, renderers); Debug.Write("Application container has been configured."); progress.Report($"Initializing shell"); settings.SettingValueChanged += (settingName, value) => { if (settingName == "Schema") { SetColorSchema((ColorSchema)value); } else if (settingName == "Language") { SetLanguage((string)value); } }; foreach (var plugin in plugins) { plugin.Initialize(); } }
private void ConfigureContainer(IProgress <string> progress) { kernel.Bind <ICommandLineArgs>().ToConstant(commandLineArgs).InSingletonScope(); kernel.Bind <ISettings, Settings>().To <Settings>().InSingletonScope(); kernel.Bind <ISky, Sky>().To <Sky>().InSingletonScope(); kernel.Bind <ISkyMap, SkyMap>().To <SkyMap>().InSingletonScope(); kernel.Bind <IGeoLocationsManager, GeoLocationsManager>().To <GeoLocationsManager>().InSingletonScope(); kernel.Bind <IMainWindow, MainVM>().To <MainVM>().InSingletonScope(); kernel.Bind <UIElementsIntegration>().ToSelf().InSingletonScope(); UIElementsIntegration uiIntegration = kernel.Get <UIElementsIntegration>(); ICollection <AbstractPlugin> plugins = new List <AbstractPlugin>(); string homeFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); IEnumerable <string> pluginPaths = Directory.EnumerateFiles(homeFolder, "Astrarium.Plugins.*.dll", SearchOption.AllDirectories); progress.Report("Loading plugins"); foreach (string path in pluginPaths) { try { var plugin = Assembly.UnsafeLoadFrom(path); // get singletons defined in plugin var singletons = plugin.GetExportedTypes().Where(t => t.IsDefined(typeof(SingletonAttribute), false)).ToArray(); foreach (var singletonImpl in singletons) { var singletonAttr = singletonImpl.GetCustomAttribute <SingletonAttribute>(); if (singletonAttr.InterfaceType != null) { if (!singletonAttr.InterfaceType.IsAssignableFrom(singletonImpl)) { throw new Exception($"Interface type {singletonAttr.InterfaceType} is not assignable from {singletonImpl}"); } kernel.Bind(singletonAttr.InterfaceType).To(singletonImpl).InSingletonScope(); } else { kernel.Bind(singletonImpl).ToSelf().InSingletonScope(); } } Log.Info($"Loaded plugin {plugin.FullName}"); } catch (Exception ex) { Log.Error($"Unable to load plugin assembly with path {path}. {ex})"); } } // collect all plugins implementations Type[] pluginTypes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .Where(t => typeof(AbstractPlugin).IsAssignableFrom(t) && !t.IsAbstract) .ToArray(); // collect all calculators types Type[] calcTypes = pluginTypes .SelectMany(p => GetCalculators(p)) .ToArray(); foreach (Type calcType in calcTypes) { var types = new[] { calcType }.Concat(calcType.GetInterfaces()).ToArray(); kernel.Bind(types).To(calcType).InSingletonScope(); } // collect all renderers types Type[] rendererTypes = pluginTypes .SelectMany(p => GetRenderers(p)) .ToArray(); foreach (Type rendererType in rendererTypes) { var types = new[] { rendererType }.Concat(rendererType.GetInterfaces()).ToArray(); kernel.Bind(types).To(rendererType).InSingletonScope(); } // collect all event provider implementations Type[] eventProviderTypes = pluginTypes .SelectMany(p => GetAstroEventProviders(p)) .ToArray(); foreach (Type eventProviderType in eventProviderTypes) { var types = new[] { eventProviderType }.Concat(eventProviderType.GetInterfaces()).ToArray(); kernel.Bind(types).To(eventProviderType).InSingletonScope(); } foreach (Type pluginType in pluginTypes) { progress.Report($"Creating plugin {pluginType}"); try { // plugin is a singleton kernel.Bind(pluginType).ToSelf().InSingletonScope(); var plugin = kernel.Get(pluginType) as AbstractPlugin; // add settings definitions uiIntegration.SettingDefinitions.AddRange(plugin.SettingDefinitions); // add settings sections uiIntegration.SettingSections.AddRange(plugin.SettingSections); // add configured toolbar buttons uiIntegration.ToolbarButtons.AddRange(plugin.ToolbarItems); // add menu items uiIntegration.MenuItems.AddRange(plugin.MenuItems); plugins.Add(plugin); } catch (Exception ex) { Log.Error($"Unable to create plugin of type {pluginType.Name}: {ex}"); kernel.Unbind(pluginType); } } progress.Report($"Creating renderers"); var renderers = rendererTypes.Select(r => kernel.Get(r)).Cast <BaseRenderer>().ToArray(); var defaultRenderingOrder = new RenderingOrder(renderers.OrderBy(r => r.Order).Select(r => new RenderingOrderItem(r))); uiIntegration.SettingDefinitions.Add(new SettingDefinition("RenderingOrder", defaultRenderingOrder, false)); var settings = kernel.Get <ISettings>(); settings.Define(uiIntegration.SettingDefinitions); settings.Save("Defaults"); progress.Report($"Loading settings"); settings.Load(); SetLanguage(settings.Get <string>("Language")); SetColorSchema(settings.Get <ColorSchema>("Schema"), settings.Get("AppTheme", "DeepBlue")); SkyContext context = new SkyContext( new Date(DateTime.Now).ToJulianEphemerisDay(), new CrdsGeographical(settings.Get <CrdsGeographical>("ObserverLocation"))); progress.Report($"Creating calculators"); var calculators = calcTypes .Select(c => kernel.Get(c)) .Cast <BaseCalc>() .ToArray(); progress.Report($"Creating event providers"); var eventProviders = eventProviderTypes .Select(c => kernel.Get(c)) .Cast <BaseAstroEventsProvider>() .ToArray(); progress.Report($"Initializing sky"); kernel.Get <Sky>().Initialize(context, calculators, eventProviders); progress.Report($"Initializing sky map"); kernel.Get <SkyMap>().Initialize(context, renderers); Log.Debug("Application container has been configured."); progress.Report($"Initializing shell"); settings.SettingValueChanged += (settingName, value) => { if (settingName == "Schema" || settingName == "AppTheme") { SetColorSchema(settings.Get("Schema", ColorSchema.Night), settings.Get("AppTheme", "DeepBlue")); } else if (settingName == "Language") { SetLanguage((string)value); } }; foreach (var plugin in plugins) { plugin.Initialize(); } }