/// <summary> /// Creates an engine with the specified application state, configuration, and service provider. /// </summary> /// <param name="applicationState">The state of the application (or <c>null</c> for an empty application state).</param> /// <param name="serviceCollection">The service collection (or <c>null</c> for an empty default service collection).</param> /// <param name="configuration">The application configuration.</param> /// <param name="settings">Settings that should override configuration values.</param> /// <param name="classCatalog">A class catalog of all assemblies in scope.</param> public Engine( ApplicationState applicationState, IServiceCollection serviceCollection, IConfiguration configuration, IEnumerable <KeyValuePair <string, object> > settings, ClassCatalog classCatalog) { _pipelines = new PipelineCollection(this); ApplicationState = applicationState ?? new ApplicationState(null, null, null); ClassCatalog = classCatalog ?? new ClassCatalog(); ClassCatalog.Populate(); ScriptHelper = new ScriptHelper(this); Settings = new ConfigurationSettings( this, configuration ?? new ConfigurationRoot(Array.Empty <IConfigurationProvider>()), settings); _serviceScope = GetServiceScope(serviceCollection); _logger = Services.GetRequiredService <ILogger <Engine> >(); DocumentFactory = new DocumentFactory(this, Settings); _diagnosticsTraceListener = new DiagnosticsTraceListener(_logger); System.Diagnostics.Trace.Listeners.Add(_diagnosticsTraceListener); // Add the service-based pipelines as late as possible so other services have been configured AddServicePipelines(); }
/// <summary> /// Initializes a new instance of the <see cref="Configurator"/> class. This overload /// allows passing in a <see cref="Preprocessor"/> that can be reused and pre-configured /// with directives not sourced from the script. /// </summary> /// <param name="engine">The engine to configure.</param> /// <param name="preprocessor">The preprocessor.</param> public Configurator(Engine engine, Preprocessor preprocessor) { _engine = engine; _preprocessor = preprocessor; _assemblyResolver = new AssemblyResolver(_scriptManager); AssemblyLoader = new AssemblyLoader(engine.FileSystem, _assemblyResolver); PackageInstaller = new PackageInstaller(engine.FileSystem, AssemblyLoader); ClassCatalog = new ClassCatalog(); engine.Namespaces.Add(typeof(ScriptBase).Namespace); }
private void CatalogClasses() { System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); using (Trace.WithIndent().Information("Cataloging classes")) { ClassCatalog.CatalogTypes(AssemblyLoader.DirectAssemblies); stopwatch.Stop(); Trace.Information($"Classes cataloged in {stopwatch.ElapsedMilliseconds} ms"); } }
private void AddNamespaces() { // Add all Wyam.Common namespaces _engine.Namespaces.AddRange(typeof(IModule).Assembly.GetTypes() .Where(x => !string.IsNullOrWhiteSpace(x.Namespace)) .Select(x => x.Namespace) .Distinct()); // Add all module namespaces _engine.Namespaces.AddRange(ClassCatalog.GetClasses <IModule>().Select(x => x.Namespace)); }
/// <summary> /// Initializes a new instance of the <see cref="Configurator"/> class. This overload /// allows passing in a <see cref="Preprocessor"/> that can be reused and pre-configured /// with directives not sourced from the script. /// </summary> /// <param name="engine">The engine to configure.</param> /// <param name="preprocessor">The preprocessor.</param> public Configurator(Engine engine, Preprocessor preprocessor) { _engine = engine; _preprocessor = preprocessor; _assemblyResolver = new AssemblyResolver(_scriptManager); AssemblyLoader = new AssemblyLoader(engine.FileSystem, engine.Assemblies, _assemblyResolver); PackageInstaller = new PackageInstaller(engine.FileSystem, AssemblyLoader); ClassCatalog = new ClassCatalog(); // Add this namespace and assembly engine.Namespaces.Add(typeof(ScriptBase).Namespace); engine.Assemblies.Add(typeof(ScriptBase).Assembly); }
private void AddShortcodes() { foreach (Type shortcode in ClassCatalog.GetClasses <IShortcode>()) { _engine.Shortcodes.Add(shortcode); // Special case for the meta shortcode to register with the name "=" if (shortcode.Equals(typeof(Core.Shortcodes.Metadata.Meta))) { _engine.Shortcodes.Add("=", shortcode); } } }
private void AddNamespaces() { // Add all Wyam.Common namespaces // the JetBrains.Profiler filter is needed due to DotTrace dynamically // adding a reference to that assembly when running under its profiler. We want // to exclude it. _engine.Namespaces.AddRange(typeof(IModule).Assembly.GetTypes() .Where(x => !string.IsNullOrWhiteSpace(x.Namespace) && !x.Namespace.StartsWith("JetBrains.Profiler")) .Select(x => x.Namespace) .Distinct()); // Add all module namespaces _engine.Namespaces.AddRange(ClassCatalog.GetClasses <IModule>().Select(x => x.Namespace)); }
private void ApplyRecipe() { if (Recipe == null && !string.IsNullOrEmpty(RecipeName)) { Recipe = ClassCatalog.GetInstance <IRecipe>(RecipeName, true); if (Recipe == null) { throw new Exception($"The recipe \"{RecipeName}\" could not be found"); } } if (Recipe != null) { _engine.Namespaces.Add(Recipe.GetType().Namespace); // Add the recipe namespace so it's available to modules Recipe.Apply(_engine); } }
private void Evaluate(string code) { if (string.IsNullOrEmpty(code)) { return; } Stopwatch stopwatch = Stopwatch.StartNew(); using (Trace.WithIndent().Information("Evaluating configuration script")) { CacheManager cacheManager = new CacheManager(_engine, _scriptManager, ConfigDllPath, ConfigHashPath, OutputScriptPath); cacheManager.EvaluateCode(code, ClassCatalog.GetClasses <IModule>().ToList(), OutputScript, IgnoreConfigHash, NoOutputConfigAssembly); stopwatch.Stop(); Trace.Information($"Evaluated configuration script in {stopwatch.ElapsedMilliseconds} ms"); } }
private void Evaluate(string code) { if (string.IsNullOrEmpty(code)) { return; } System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); using (Trace.WithIndent().Information("Evaluating configuration script")) { _scriptManager.Create(code, ClassCatalog.GetClasses <IModule>().ToList(), _engine.Namespaces); WriteScript(_scriptManager.Code); _scriptManager.Compile(AppDomain.CurrentDomain.GetAssemblies()); _engine.DynamicAssemblies.Add(_scriptManager.RawAssembly); _scriptManager.Evaluate(_engine); stopwatch.Stop(); Trace.Information($"Evaluated configuration script in {stopwatch.ElapsedMilliseconds} ms"); } }
private void AddFileProviders() { foreach (IFileProvider fileProvider in ClassCatalog.GetInstances <IFileProvider>()) { string scheme = fileProvider.GetType().Name.ToLowerInvariant(); if (scheme.EndsWith("fileprovider")) { scheme = scheme.Substring(0, scheme.Length - 12); } if (scheme.EndsWith("provider")) { scheme = scheme.Substring(0, 8); } if (!string.IsNullOrEmpty(scheme)) { _engine.FileSystem.FileProviders.Add(scheme, fileProvider); } } }
/// <summary> /// Adds all services required for the <see cref="RenderRazor"/> module. /// </summary> /// <param name="serviceCollection">The service collection to register services in.</param> /// <param name="fileSystem">The file system or <c>null</c> to skip.</param> /// <param name="classCatalog">An existing class catalog or <c>null</c> to scan assemblies during registration.</param> /// <returns>The service collection.</returns> public static IServiceCollection AddRazor(this IServiceCollection serviceCollection, IReadOnlyFileSystem fileSystem, ClassCatalog classCatalog = null) { // Register the file system if we're not expecting one from an engine if (fileSystem != null) { serviceCollection.TryAddSingleton(fileSystem); } // Register some of our own types if not already registered serviceCollection.TryAddSingleton <Microsoft.Extensions.FileProviders.IFileProvider, FileSystemFileProvider>(); serviceCollection.TryAddSingleton <DiagnosticSource, SilentDiagnosticSource>(); serviceCollection.TryAddSingleton(new DiagnosticListener("Razor")); serviceCollection.TryAddSingleton <IWebHostEnvironment, HostEnvironment>(); serviceCollection.TryAddSingleton <ObjectPoolProvider, DefaultObjectPoolProvider>(); serviceCollection.TryAddSingleton <StatiqRazorProjectFileSystem>(); serviceCollection.TryAddSingleton <RazorProjectFileSystem, StatiqRazorProjectFileSystem>(); // Register the view location expander if not already registered serviceCollection.Configure <RazorViewEngineOptions>(x => { if (!x.ViewLocationExpanders.OfType <ViewLocationExpander>().Any()) { x.ViewLocationExpanders.Add(new ViewLocationExpander()); } }); // Add the default services _after_ adding our own // (most default registration use .TryAdd...() so they skip already registered types) IMvcCoreBuilder builder = serviceCollection .AddMvcCore() .AddRazorViewEngine() .AddRazorRuntimeCompilation(); // Add all loaded assemblies CompilationReferencesProvider referencesProvider = new CompilationReferencesProvider(); referencesProvider.Assemblies.AddRange((classCatalog ?? new ClassCatalog()).GetAssemblies()); // And a couple needed assemblies that might not be loaded in the AppDomain yet referencesProvider.Assemblies.Add(typeof(IHtmlContent).Assembly); referencesProvider.Assemblies.Add(Assembly.Load(new AssemblyName("Microsoft.CSharp"))); // Add the reference provider as an ApplicationPart builder.ConfigureApplicationPartManager(x => x.ApplicationParts.Add(referencesProvider)); return(serviceCollection); }