public void Init(string modulePath, string moduleClrType, string moduleName, JsonValue moduleSettings, LoggerBase log, ISettingsSaver saver) { _log = log; _moduleName = moduleName; var assembly = Assembly.LoadFile(modulePath); Type moduleType; if (moduleClrType != null) { moduleType = Type.GetType(moduleClrType); if (moduleType == null) { throw new ModuleInitializationException("The specified CLR type {0} is invalid.".Fmt(moduleClrType)); } } else { var candidates = assembly.GetExportedTypes().Where(type => typeof(IPropellerModule).IsAssignableFrom(type) && !type.IsAbstract).Take(2).ToArray(); if (candidates.Length == 0) { throw new ModuleInitializationException("The file {0} does not contain a Propeller module.".Fmt(modulePath)); } else if (candidates.Length == 2) { throw new ModuleInitializationException("The file {0} contains multiple Propeller modules ({1} and {2}). Specify the desired module type explicitly.".Fmt(modulePath, candidates[0].FullName, candidates[1].FullName)); } moduleType = candidates[0]; } _module = (IPropellerModule)Activator.CreateInstance(moduleType); _module.Init(log, moduleSettings, saver); }
/// <summary> /// Executes a Propeller module in standalone mode (as opposed to being hosted by the Propeller engine).</summary> /// <param name="module"> /// An instance of the module to be executed.</param> /// <param name="settingsPath"> /// Path and filename of the Propeller settings file. This file must contain a Propeller configuration containing /// exactly one module configuration.</param> /// <param name="propagateExceptions"> /// Specifies whether exceptions get propagated to the debugger. Setting this to <c>true</c> will cause exceptions /// to bring down the server, so only do this when debugging.</param> public static void RunStandalone(string settingsPath, IPropellerModule module, bool propagateExceptions = false) { var settings = LoadSettings(settingsPath, new ConsoleLogger(), true); if (settings.Modules.Length == 0) { settings.Modules = Ut.NewArray(new PropellerModuleSettings { ModuleName = module.Name, ModuleDll = null, Settings = new JsonDict(), Hooks = Ut.NewArray(new UrlHook(domain: "localhost", protocols: Protocols.All)) }); } if (settings.Modules.Length != 1) { throw new InvalidOperationException("Propeller Standalone mode can only accept a settings file that has exactly one module configuration."); } var log = GetLogger(true, settings.LogFile, settings.LogVerbosity); log.Info("Running Propeller module {0} in standalone mode.".Fmt(module.Name)); var resolver = new UrlResolver(); var server = new HttpServer(settings.ServerOptions) { Handler = resolver.Handle, PropagateExceptions = propagateExceptions }; var pretendPluginPath = PathUtil.AppPathCombine(module.Name + ".dll"); module.Init(log, settings.Modules[0].Settings, new SettingsSaver(s => { settings.Modules[0].Settings = s; try { settings.Save(settingsPath); } catch (Exception e) { log.Error("Error saving settings for module {0}:".Fmt(settings.Modules[0].ModuleName)); LogException(log, e); } })); if (settings.Modules[0].Hooks.Length == 0) { log.Warn("The settings did not configure any UrlHook for the module. It will not be accessible through any URL."); } else { foreach (var hook in settings.Modules[0].Hooks) { resolver.Add(new UrlMapping(hook, module.Handle)); } log.Info("Module URLs: " + settings.Modules[0].Hooks.JoinString("; ")); } log.Info("Starting server on {0}.".Fmt(settings.ServerOptions.Endpoints.Select(ep => "port " + ep.Value.Port + (ep.Value.Secure ? " (HTTPS)" : " (HTTP)")).JoinString(", "))); settings.Save(settingsPath); server.StartListening(true); }