/// <summary>
        /// Creates and starts a persistence-less App Host that doesn't have a database connection. A transient host is very light-weight and
        /// although its state is not persisted (the Orchard shell state; any persistence you do will work of course) it's kept until the
        /// Host is disposed. That means you can still enabled/disable features for example and the shell state will change as expected.
        /// </summary>
        /// <param name="settings">Settings for the App Host.</param>
        /// <param name="registrations">Dependency registrations for the App Host.</param>
        /// <param name="enabledStartupFeatures">Names of features to enable already when the shell starts.</param>
        public static Task <IOrchardAppHost> StartTransientHost(AppHostSettings settings, AppHostRegistrations registrations, IEnumerable <ShellFeature> enabledStartupFeatures)
        {
            if (registrations == null)
            {
                registrations = new AppHostRegistrations();
            }

            var appRegistrations = (registrations.HostRegistrations == null) ? builder => { } : registrations.HostRegistrations;

            registrations.HostRegistrations = builder =>
            {
                var shellSettingsManager = new TransientShellSettingsManager();
                shellSettingsManager.SaveSettings(new ShellSettings {
                    Name = ShellSettings.DefaultName, State = TenantState.Running
                });
                builder.RegisterInstance(shellSettingsManager).As <IShellSettingsManager>().SingleInstance();

                builder.RegisterType <HostTransientStore>().As <IHostTransientStore>().SingleInstance();

                appRegistrations(builder);
            };

            var shellRegistrations = (registrations.ShellRegistrations == null) ? builder => { } : registrations.ShellRegistrations;

            registrations.ShellRegistrations = builder =>
            {
                if (enabledStartupFeatures == null)
                {
                    enabledStartupFeatures = Enumerable.Empty <ShellFeature>();
                }
                enabledStartupFeatures = enabledStartupFeatures.Union(new[]
                {
                    new ShellFeature {
                        Name = "Orchard.Framework"
                    },
                    new ShellFeature {
                        Name = "Lombiq.OrchardAppHost.TransientHost"
                    }
                });

                builder
                .RegisterInstance(new DefaultTransientShellDescriptorProvider(new ShellDescriptor {
                    Features = enabledStartupFeatures
                }))
                .As <IDefaultTransientShellDescriptorProvider>();

                builder.RegisterType <TransientShellDescriptorManager>().As <IShellDescriptorManager>().SingleInstance();
                builder.RegisterType <TransientShellStateManager>().As <IShellStateManager>().SingleInstance();
                builder.RegisterType <TransientStore>().As <ITransientStore>().SingleInstance();

                // These below are only needed if Core extensions are not loaded (i.e. their path not set in AppHostSettings).
                // Needed too early in ShellContextFactory, since the minimum shell doesn't include any external feautures.
                builder.RegisterType <NullSiteService>().As <ISiteService>().SingleInstance();
                builder.RegisterType <NullContentDefinitionManager>().As <IContentDefinitionManager>().SingleInstance();

                shellRegistrations(builder);
            };

            return(StartHost(settings, registrations));
        }
        /// <summary>
        /// Creates and starts an App Host.
        /// </summary>
        /// <param name="settings">Settings for the App Host.</param>
        /// <param name="registrations">Dependency registrations for the App Host.</param>
        public static async Task <IOrchardAppHost> StartHost(AppHostSettings settings, AppHostRegistrations registrations)
        {
            var host = new OrchardAppHost(settings, registrations);
            await host.Startup();

            return(host);
        }
示例#3
0
        public static async Task RunSample(AppHostSettings settings)
        {
            Console.WriteLine("=== Loop sample starts === ");
            Console.WriteLine("Press Ctrl+C to exit the loop.");

            using (var host = await OrchardAppHostFactory.StartHost(settings))
            {
                var run = true;

                // Hit Ctrl+C to exit the loop, but not the app (other samples will follow up).
                Console.CancelKeyPress += (sender, e) =>
                {
                    e.Cancel = true;
                    run      = false;
                };


                while (run)
                {
                    Console.WriteLine("Cycle starts.");


                    await host.Run <ILoggerService, IClock>((logger, clock) => Task.Run(() =>
                    {
                        logger.Error("Test log entry.");
                        Console.WriteLine(clock.UtcNow.ToString());
                    }));

                    // Another overload of Run() for simple transaction handling and for using the work context scope
                    // directly.
                    await host.RunInTransaction(async scope =>
                    {
                        Console.WriteLine(scope.Resolve <ISiteService>().GetSiteSettings().SiteName);

                        // Simulating an async call. Because of this the delegate is marked as async (and we don't
                        // need to wrap it into a Task.Run()).
                        await Task.Delay(3000);

                        Console.WriteLine(scope.Resolve <ISiteService>().GetSiteSettings().SiteName);
                        Console.WriteLine(scope.Resolve <ShellSettings>().Name);
                    });


                    Console.WriteLine("Cycle ends.");
                    Console.WriteLine();
                }
            }

            Console.WriteLine("=== Loop sample ended === ");
        }
示例#4
0
        public OrchardAppHost(
            AppHostSettings settings,
            AppHostRegistrations registrations)
        {
            if (settings == null)
            {
                settings = new AppHostSettings();
            }
            if (registrations == null)
            {
                registrations = new AppHostRegistrations();
            }

            _settings      = settings;
            _registrations = registrations;
        }
        static void Main(string[] args)
        {
            Task.Run(async() =>
            {
                // There are a lot of settings you can use.
                var settings = new AppHostSettings
                {
                    // A random App_Data folder so the setup sample can run from a fresh state.
                    AppDataFolderPath         = "~/App_Data" + new Random().Next(),
                    ModuleFolderPaths         = new[] { @"~/../../../Orchard/src/Orchard.Web/Modules" },
                    CoreModuleFolderPaths     = new[] { @"~/../../../Orchard/src/Orchard.Web/Core" },
                    ThemeFolderPaths          = new[] { @"~/../../../Orchard/src/Orchard.Web/Themes" },
                    ImportedExtensions        = new[] { typeof(Program).Assembly },
                    DefaultShellFeatureStates = new[]
                    {
                        new DefaultShellFeatureState
                        {
                            ShellName       = ShellSettings.DefaultName,
                            EnabledFeatures = new[]
                            {
                                "Lombiq.OrchardAppHost.Sample",
                                "Lombiq.OrchardAppHost.Sample.ShellEvents"
                            }
                        }
                    },
                    DisableConfiguratonCaches  = true,
                    DisableExtensionMonitoring = true,
                    // Configuring the logging of SQL queries (see:
                    // http://weblogs.asp.net/bleroy/logging-sql-queries-in-orchard).
                    // This needs a reference to the Log4Net assembly.
                    Log4NetConfigurator = loggerRespository =>
                                          ((Logger)loggerRespository.GetLogger("NHibernate.SQL")).Level = Level.Debug
                };


                // Samples are being run below, check out the static classes.

                await SetupSample.RunSample(settings);
                Console.WriteLine();
                await LoopSample.RunSample(settings);
                Console.WriteLine();
                await TransientHostSample.RunSample(settings);


                Console.ReadKey();
            }).Wait();     // This is a workaround just to be able to run all this from inside a console app.
        }
        public static async Task RunSample(AppHostSettings settings)
        {
            Console.WriteLine("=== Transient host sample starts === ");

            using (var host = await OrchardAppHostFactory.StartTransientHost(settings, null, null))
            {
                await host.Run <ITestService, ILoggerService, IClock>((testService, logger, clock) => Task.Run(() =>
                {
                    testService.Test();     // Custom dependencies from imported and enabled extensions work too.
                    logger.Error("Test log entry from transient shell.");
                    Console.WriteLine(clock.UtcNow.ToString());
                }));

                // You can even run such "getters" to just fetch something from Orchard.
                var utcNow = await host.RunGet(scope => Task.Run(() => scope.Resolve <IClock>().UtcNow));
            }

            Console.WriteLine("=== Transient host sample ended === ");
        }
        public static async Task RunSample(AppHostSettings settings)
        {
            Console.WriteLine("=== Setup sample starts === ");

            using (var host = await OrchardAppHostFactory.StartHost(settings))
            {
                // We can even run the setup on a new shell. A project reference to Orchard.Setup is needed.
                // The setup shouldn't run in a transaction.
                await host.Run <ISetupService, ShellSettings>((setupService, shellSettings) => Task.Run(() =>
                {
                    Console.WriteLine("Running setup for the following shell: " + shellSettings.Name);
                    setupService.Setup(new SetupContext
                    {
                        SiteName         = "Test",
                        AdminUsername    = "******",
                        AdminPassword    = "******",
                        DatabaseProvider = "SqlCe",
                        Recipe           = setupService.Recipes().Where(recipe => recipe.Name == "Default").Single()
                    });

                    Console.WriteLine("Setup done");
                }), wrapInTransaction : false);
            }

            using (var host = await OrchardAppHostFactory.StartHost(settings))
            {
                // After setup everything else should be run in a newly started host.
                await host.Run <ISiteService, ShellSettings>((siteService, shellSettings) => Task.Run(() =>
                {
                    Console.WriteLine(siteService.GetSiteSettings().SiteName);
                    Console.WriteLine(shellSettings.Name);
                }));
            }

            Console.WriteLine("=== Setup host sample ended === ");
        }
示例#8
0
        private async Task LoadHost()
        {
            var moduleFolderPaths = new List <string>();

            // Since Hast.Core either exists or not we need to start by probing for the Hast.Abstractions folder.
            var abstractionsPath = Path.GetDirectoryName(GetType().Assembly.Location);
            var currentDirectory = Path.GetFileName(abstractionsPath);

            if (currentDirectory.Equals("Debug", StringComparison.OrdinalIgnoreCase) ||
                currentDirectory.Equals("Release", StringComparison.OrdinalIgnoreCase))
            {
                abstractionsPath = Path.GetDirectoryName(abstractionsPath);
            }
            currentDirectory = Path.GetFileName(abstractionsPath);
            if (currentDirectory.Equals("bin", StringComparison.OrdinalIgnoreCase))
            {
                abstractionsPath = Path.GetDirectoryName(abstractionsPath);
            }

            // Now we're at the level above the current project's folder.
            abstractionsPath = Path.GetDirectoryName(abstractionsPath);

            var coreFound = false;

            while (abstractionsPath != null && !coreFound)
            {
                var abstractionsSubFolder = Path.Combine(abstractionsPath, "Hast.Abstractions");
                if (Directory.Exists(abstractionsSubFolder))
                {
                    abstractionsPath = abstractionsSubFolder;
                    coreFound        = true;
                }
                else
                {
                    abstractionsPath = Path.GetDirectoryName(abstractionsPath);
                }
            }

            // There won't be an Abstractions folder, nor a Core one when the app is being run from a deployment folder
            // (as opposed to a solution).
            if (!string.IsNullOrEmpty(abstractionsPath))
            {
                moduleFolderPaths.Add(abstractionsPath);
            }

            if (_configuration.Flavor == HastlayerFlavor.Developer)
            {
                var corePath = !string.IsNullOrEmpty(abstractionsPath) ?
                               Path.Combine(Path.GetDirectoryName(abstractionsPath), "Hast.Core") :
                               null;

                if (corePath != null && Directory.Exists(corePath))
                {
                    moduleFolderPaths.Add(corePath);
                }
            }

            var importedExtensions = new[]
            {
                typeof(Hastlayer).Assembly,
                typeof(IProxyGenerator).Assembly,
                typeof(IHardwareImplementationComposer).Assembly,
                typeof(ITransformer).Assembly,
                typeof(Nexys4DdrManifestProvider).Assembly
            }
            .ToList();

            if (_configuration.Flavor == HastlayerFlavor.Client)
            {
                importedExtensions.Add(typeof(Remote.Client.RemoteTransformer).Assembly);
            }

            // Adding imported extensions last so they can override anything.
            importedExtensions.AddRange(_configuration.Extensions);

            var settings = new AppHostSettings
            {
                // Setting a custom path so if the parent app is also an AppHost app then with the default settings
                // those won't clash.
                AppDataFolderPath         = "~/Hastlayer/App_Data",
                ImportedExtensions        = importedExtensions,
                DefaultShellFeatureStates = new[]
                {
                    new DefaultShellFeatureState
                    {
                        ShellName       = ShellName,
                        EnabledFeatures = importedExtensions.Select(extension => extension.ShortName())
                    }
                },
                ModuleFolderPaths = moduleFolderPaths
            };


            var registrations = new AppHostRegistrations
            {
                HostRegistrations = builder => builder
                                    .RegisterType <HardwareExecutionEventHandlerHolder>()
                                    .As <IHardwareExecutionEventHandlerHolder>()
                                    .SingleInstance()
            };

            _host = await OrchardAppHostFactory.StartTransientHost(settings, registrations, null);

            await _host.Run <IHardwareExecutionEventHandlerHolder>(proxy => Task.Run(() =>
                                                                                     proxy.RegisterExecutedOnHardwareEventHandler(eventArgs => ExecutedOnHardware?.Invoke(this, eventArgs))));

            // Enable all loaded features. This is needed so extensions just added to the solution, but not referenced
            // anywhere in the current app can contribute dependencies.
            await _host
            .Run <Orchard.Environment.Features.IFeatureManager>(
                (featureManager) =>
            {
                featureManager.EnableFeatures(featureManager.GetAvailableFeatures().Select(feature => feature.Id), true);

                return(Task.CompletedTask);
            }, ShellName, false);
        }
示例#9
0
 // Having an overload without "registrations" enables calling it without the caller having a reference to Autofac.
 public OrchardAppHost(AppHostSettings settings)
     : this(settings, null)
 {
 }
 public ExtensionPathsProvider(AppHostSettings hostSettings, IVirtualPathProvider virtualPathProvider)
 {
     _hostSettings        = hostSettings;
     _virtualPathProvider = virtualPathProvider;
 }
 /// <summary>
 /// Creates and starts an App Host.
 /// </summary>
 /// <param name="settings">Settings for the App Host.</param>
 public static Task <IOrchardAppHost> StartHost(AppHostSettings settings)
 {
     return(StartHost(settings, null));
 }
示例#12
0
        public static IContainer CreateHostContainer(IOrchardAppHost appHost, AppHostSettings settings, AppHostRegistrations registrations)
        {
            return(OrchardStarter.CreateHostContainer(builder =>
            {
                builder.RegisterType <AppHostEnvironment>().As <IHostEnvironment>().SingleInstance();

                // Needed also for shells, separately.
                RegisterAppDataFolderRoot(builder, settings.AppDataFolderPath).SingleInstance();

                RegisterVolatileProvider <AppHostVirtualPathMonitor, IVirtualPathMonitor>(builder);
                RegisterVolatileProvider <AppHostVirtualPathProvider, IVirtualPathProvider>(builder);
                RegisterVolatileProvider <AppHostWebSiteFolder, IWebSiteFolder>(builder);

                var shellRegistrations = new ShellContainerRegistrations
                {
                    Registrations = shellBuilder =>
                    {
                        // Despite imported assemblies being handled these registrations are necessary, because they are needed too early.
                        // Adding them as normal services, even with OrchardSuppressDependency, wouldn't work.

                        RegisterAppDataFolderRoot(shellBuilder, settings.AppDataFolderPath).InstancePerMatchingLifetimeScope("shell");

                        RegisterVolatileProviderForShell <AppHostVirtualPathMonitor, IVirtualPathMonitor>(shellBuilder);
                        RegisterVolatileProviderForShell <AppHostVirtualPathProvider, IVirtualPathProvider>(shellBuilder);
                        RegisterVolatileProviderForShell <AppHostWebSiteFolder, IWebSiteFolder>(shellBuilder);

                        if (registrations.ShellRegistrations != null)
                        {
                            registrations.ShellRegistrations(shellBuilder);
                        }
                    }
                };
                builder.RegisterInstance(shellRegistrations).As <IShellContainerRegistrations>();

                // Handling imported assemblies.
                if (settings.ImportedExtensions != null && settings.ImportedExtensions.Any())
                {
                    builder.RegisterType <ImportedExtensionsProvider>().As <IExtensionFolders, IExtensionLoader>().SingleInstance()
                    .WithParameter(new NamedParameter("extensions", settings.ImportedExtensions));
                }

                // Configuring extension loading.
                builder.RegisterType <ExtensionPathsProvider>().As <IExtensionPathsProvider>().SingleInstance()
                .WithParameter(new NamedParameter("hostSettings", settings));
                builder.RegisterType <AppHostExtensionFolders>().As <IExtensionFolders>().SingleInstance();
                builder.RegisterType <AppHostCoreExtensionLoader>().As <IExtensionLoader>().SingleInstance();
                builder.RegisterType <AppHostRawThemeExtensionLoader>().As <IExtensionLoader>().SingleInstance();

                if (settings.DisableConfiguratonCaches)
                {
                    builder.RegisterModule <ConfigurationCacheDisablingModule>();
                }

                if (settings.DisableExtensionMonitoring)
                {
                    builder.RegisterModule <ExtensionMonitoringDisablingModule>();
                }

                // Either we register MVC singletons or we need at least a new IOrchardShell implementation.
                builder.Register(ctx => RouteTable.Routes).SingleInstance();
                builder.Register(ctx => ModelBinders.Binders).SingleInstance();
                builder.Register(ctx => ViewEngines.Engines).SingleInstance();

                builder.RegisterType <LoggerService>().As <ILoggerService>().SingleInstance();

                builder.RegisterInstance(appHost).As <IOrchardAppHost>().ExternallyOwned();

                if (registrations.HostRegistrations != null)
                {
                    registrations.HostRegistrations(builder);
                }
            }));
        }