public OrchardAppHost(
            AppHostSettings settings,
            AppHostRegistrations registrations)
        {
            if (settings == null) settings = new AppHostSettings();
            if (registrations == null) registrations = new AppHostRegistrations();

            _settings = settings;
            _registrations = registrations;
        }
        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 === ");
        }
        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.
        }
        /// <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);
        }
        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 === ");
        }
 /// <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;
 }
 /// <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);
 }
 public ExtensionPathsProvider(AppHostSettings hostSettings, IVirtualPathProvider virtualPathProvider)
 {
     _hostSettings = hostSettings;
     _virtualPathProvider = virtualPathProvider;
 }
 // Having an overload without "registrations" enables calling it without the caller having a reference to Autofac.
 public OrchardAppHost(AppHostSettings settings)
     : this(settings, null)
 {
 }