src/Dimmy.DevelopmentHelper/Dimmy.DevelopmentHelper.10.1.0/Initialiser.cs (151 lines of code) (raw):

using System; using System.Configuration; using System.IO; using System.Linq; using System.Reflection; using System.Web; using System.Web.Configuration; using Dimmy.DevelopmentHelper._10._1._0; using Sitecore.Configuration; using Sitecore.UpdateCenter.Services.UpdateMode; [assembly: PreApplicationStartMethod(typeof(Initialiser), nameof(Initialiser.Initialise))] namespace Dimmy.DevelopmentHelper._10._1._0 { public static class Initialiser { private const string DevelopmentPerformanceConfigResourceName = "Dimmy.DevelopmentHelper._10._1._0.DevelopmentPerformance.config"; private const string WorkCompleteResourceName = "Dimmy.DevelopmentHelper._10._1._0.workcomplete"; private static readonly string HookBindMountBinPath; private static readonly string HookName; private static readonly string WorkCompletePath; private static Configuration _config; static Initialiser() { HookName = Environment.GetEnvironmentVariable("DEVELOPMENTHELPER_HOOK_NAME"); if(HookName == null) return; WorkCompletePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ".workcomplete"); HookBindMountBinPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, HookName, "bin"); AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; } public static void Initialise() { LoadDeploymentHookAssemblies(); if (WorkComplete()) return; _config = WebConfigurationManager.OpenWebConfiguration("~"); ApplyWebConfigChanges(); AddDevelopmentPerformanceConfigToSitecoreIncludes(); AddHookLayer(); SetWorkComplete(); _config.Save(); } private static void SetWorkComplete() { var workComplete = GetManifestResourceString(WorkCompleteResourceName); File.WriteAllText(WorkCompletePath, workComplete); } private static void AddDevelopmentPerformanceConfigToSitecoreIncludes() { var developmentPerformance = GetManifestResourceString(DevelopmentPerformanceConfigResourceName); var developmentPerformancePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Config", "Include", "zzz"); if (!Directory.Exists(developmentPerformancePath)) Directory.CreateDirectory(developmentPerformancePath); var developmentPerformanceFilePath = Path.Combine(developmentPerformancePath, "DevelopmentPerformance.config"); File.WriteAllText(developmentPerformanceFilePath, developmentPerformance); } private static string GetManifestResourceString(string manifestResourceStreamName) { try { using (var stream = typeof(Initialiser).Assembly.GetManifestResourceStream(manifestResourceStreamName)) { if (stream == null) { throw new InvalidOperationException("Could not load manifest resource stream."); } using (var reader = new StreamReader(stream)) { return reader.ReadToEnd(); } } } catch (Exception e) { var objAssembly = typeof(Initialiser).Assembly; var strResourceNames = objAssembly.GetManifestResourceNames(); throw new Exception("Resource names:" + string.Join(" ", strResourceNames), e); } } private static void ApplyWebConfigChanges() { var section = _config.GetSectionGroup("system.web")?.Sections["compilation"]; if (!(section is CompilationSection compilationSection) || compilationSection.OptimizeCompilations) return; compilationSection.OptimizeCompilations = true; } private static bool WorkComplete() { return File.Exists(WorkCompletePath); } private static void AddHookLayer() { var providerHelper = new ConfigurationProviderHelper(); var layeredConfiguration = new LayeredConfigurationFiles(); var configurationLayerProvider = layeredConfiguration.ConfigurationLayerProviders.FirstOrDefault(); if (configurationLayerProvider != null && configurationLayerProvider.GetLayers().Any(l => l.Name == HookName)) return; if (!(configurationLayerProvider is DefaultConfigurationLayerProvider defaultConfigurationLayerProvider)) return; var applicationLayer = new DefaultConfigurationLayer(HookName, $"{HookName}/App_Config/Include/"); AddLayer("Foundation", applicationLayer); AddLayer("Feature", applicationLayer); AddLayer("Project", applicationLayer); defaultConfigurationLayerProvider.AddLayer(applicationLayer); providerHelper.SaveConfigurationProvider(configurationLayerProvider); } private static void AddLayer(string layerName, DefaultConfigurationLayer ddApplicationLayer) { var configEntryInfo = new DefaultConfigurationLayer.ConfigEntryInfo { Path = layerName, Type = DefaultConfigurationLayer.ConfigEntryType.Folder, Enabled = true }; ddApplicationLayer.LoadOrder.Add(configEntryInfo); } private static void LoadDeploymentHookAssemblies() { if(HookBindMountBinPath == null) return; var hookBindMountBinDirectory = new DirectoryInfo(HookBindMountBinPath); var hookBindMountAssemblies = hookBindMountBinDirectory.GetFiles("*.dll", SearchOption.TopDirectoryOnly); var assemblyDictionary = AppDomain.CurrentDomain.GetAssemblies() .ToDictionary(x => x.GetName(), x => x); foreach (var file in hookBindMountAssemblies) { var assemblyFile = File.ReadAllBytes(file.FullName); var assemblyName = Assembly.Load(assemblyFile).GetName(); if (assemblyDictionary.ContainsKey(assemblyName)) continue; //equivalent to adding the assembly name to compilation/assemblies in web.config AppDomain.CurrentDomain.Load(assemblyFile); } } private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { // Ignore missing resources if (args.Name.Contains(".resources")) return null; // check for assemblies already loaded var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name); if (assembly != null) return assembly; var assemblyPath = Path.Combine(HookBindMountBinPath, new AssemblyName(args.Name).Name + ".dll"); if (!File.Exists(assemblyPath)) return null; try { var assemblyFile = File.ReadAllBytes(assemblyPath); return Assembly.Load(assemblyFile); } catch (Exception ex) { return null; } } } }