New IRuntimeHash to fix type scanning in netcore in order to look at the right runtime bits to creaet a hash for
This commit is contained in:
@@ -131,8 +131,8 @@ namespace Umbraco.Core.Configuration.Legacy
|
||||
if (_reservedPaths != null) return _reservedPaths;
|
||||
|
||||
var reservedPaths = StaticReservedPaths;
|
||||
var umbPath = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path) && !ConfigurationManager.AppSettings[Constants.AppSettings.Path].IsNullOrWhiteSpace()
|
||||
? ConfigurationManager.AppSettings[Constants.AppSettings.Path]
|
||||
var umbPath = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.UmbracoPath) && !ConfigurationManager.AppSettings[Constants.AppSettings.UmbracoPath].IsNullOrWhiteSpace()
|
||||
? ConfigurationManager.AppSettings[Constants.AppSettings.UmbracoPath]
|
||||
: "~/umbraco";
|
||||
//always add the umbraco path to the list
|
||||
reservedPaths += umbPath.EnsureEndsWith(',');
|
||||
@@ -146,12 +146,6 @@ namespace Umbraco.Core.Configuration.Legacy
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to umbraco's root directory (/umbraco by default).
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
public string Path => ConfigurationManager.AppSettings[Constants.AppSettings.Path];
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance.
|
||||
/// </summary>
|
||||
|
||||
@@ -30,8 +30,6 @@ namespace Umbraco.Configuration.Models
|
||||
public string ReservedUrls => _configuration.GetValue(Prefix + "ReservedUrls", StaticReservedUrls);
|
||||
public string ReservedPaths => _configuration.GetValue(Prefix + "ReservedPaths", StaticReservedPaths);
|
||||
|
||||
public string Path => _configuration.GetValue<string>(Prefix + "Path");
|
||||
|
||||
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
|
||||
public string ConfigurationStatus
|
||||
{
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to create a hash value of the current runtime
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used to detect if the runtime itself has changed, like a DLL has changed or another dynamically compiled
|
||||
/// part of the application has changed. This is used to detect if we need to re-type scan.
|
||||
/// </remarks>
|
||||
public interface IRuntimeHash
|
||||
{
|
||||
string GetHashValue();
|
||||
}
|
||||
}
|
||||
@@ -51,5 +51,14 @@ namespace Umbraco.Core.Composing
|
||||
Type attributeType,
|
||||
IEnumerable<Assembly> assemblies,
|
||||
bool onlyConcreteClasses);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a hash value of the current runtime
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used to detect if the runtime itself has changed, like a DLL has changed or another dynamically compiled
|
||||
/// part of the application has changed. This is used to detect if we need to re-type scan.
|
||||
/// </remarks>
|
||||
string GetRuntimeHash();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the runtime hash based on file system paths to scan
|
||||
/// </summary>
|
||||
public class RuntimeHash : IRuntimeHash
|
||||
{
|
||||
private readonly IProfilingLogger _logger;
|
||||
private readonly RuntimeHashPaths _paths;
|
||||
|
||||
public RuntimeHash(IProfilingLogger logger, RuntimeHashPaths paths)
|
||||
{
|
||||
_logger = logger;
|
||||
_paths = paths;
|
||||
}
|
||||
|
||||
|
||||
public string GetHashValue()
|
||||
{
|
||||
var allPaths = _paths.GetFolders()
|
||||
.Select(x => ((FileSystemInfo) x, false))
|
||||
.Concat(_paths.GetFiles().Select(x => ((FileSystemInfo) x.Key, x.Value)));
|
||||
|
||||
var hash = GetFileHash(allPaths);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a unique hash for a combination of FileInfo objects.
|
||||
/// </summary>
|
||||
/// <param name="filesAndFolders">A collection of files.</param>
|
||||
/// <returns>The hash.</returns>
|
||||
/// <remarks>Each file is a tuple containing the FileInfo object and a boolean which indicates whether to hash the
|
||||
/// file properties (false) or the file contents (true).</remarks>
|
||||
private string GetFileHash(IEnumerable<(FileSystemInfo fileOrFolder, bool scanFileContent)> filesAndFolders)
|
||||
{
|
||||
using (_logger.DebugDuration<TypeLoader>("Determining hash of code files on disk", "Hash determined"))
|
||||
{
|
||||
// get the distinct file infos to hash
|
||||
var uniqInfos = new HashSet<string>();
|
||||
var uniqContent = new HashSet<string>();
|
||||
|
||||
using var generator = new HashGenerator();
|
||||
|
||||
foreach (var (fileOrFolder, scanFileContent) in filesAndFolders)
|
||||
{
|
||||
if (scanFileContent)
|
||||
{
|
||||
// add each unique file's contents to the hash
|
||||
// normalize the content for cr/lf and case-sensitivity
|
||||
if (uniqContent.Add(fileOrFolder.FullName))
|
||||
{
|
||||
if (File.Exists(fileOrFolder.FullName) == false) continue;
|
||||
var content = RemoveCrLf(File.ReadAllText(fileOrFolder.FullName));
|
||||
generator.AddCaseInsensitiveString(content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add each unique folder/file to the hash
|
||||
if (uniqInfos.Add(fileOrFolder.FullName))
|
||||
{
|
||||
generator.AddFileSystemItem(fileOrFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
return generator.GenerateHash();
|
||||
}
|
||||
}
|
||||
|
||||
// fast! (yes, according to benchmarks)
|
||||
private static string RemoveCrLf(string s)
|
||||
{
|
||||
var buffer = new char[s.Length];
|
||||
var count = 0;
|
||||
// ReSharper disable once ForCanBeConvertedToForeach - no!
|
||||
for (var i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (s[i] != '\r' && s[i] != '\n')
|
||||
buffer[count++] = s[i];
|
||||
}
|
||||
return new string(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Paths used to determine the <see cref="IRuntimeHash"/>
|
||||
/// </summary>
|
||||
public sealed class RuntimeHashPaths
|
||||
{
|
||||
private readonly List<DirectoryInfo> _paths = new List<DirectoryInfo>();
|
||||
private readonly Dictionary<FileInfo, bool> _files = new Dictionary<FileInfo, bool>();
|
||||
|
||||
public void AddFolder(DirectoryInfo pathInfo) => _paths.Add(pathInfo);
|
||||
public void AddFile(FileInfo fileInfo, bool scanFileContent = false) => _files.Add(fileInfo, scanFileContent);
|
||||
|
||||
public IEnumerable<DirectoryInfo> GetFolders() => _paths;
|
||||
public IReadOnlyDictionary<FileInfo, bool> GetFiles() => _files;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ namespace Umbraco.Core.Composing
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IAssemblyProvider _assemblyProvider;
|
||||
private readonly IRuntimeHash _runtimeHash;
|
||||
private volatile HashSet<Assembly> _localFilteredAssemblyCache;
|
||||
private readonly object _localFilteredAssemblyCacheLocker = new object();
|
||||
private readonly List<string> _notifiedLoadExceptionAssemblies = new List<string>();
|
||||
@@ -25,10 +26,11 @@ namespace Umbraco.Core.Composing
|
||||
// used for benchmark tests
|
||||
internal bool QueryWithReferencingAssemblies = true;
|
||||
|
||||
public TypeFinder(ILogger logger, IAssemblyProvider assemblyProvider, ITypeFinderConfig typeFinderConfig = null)
|
||||
public TypeFinder(ILogger logger, IAssemblyProvider assemblyProvider, IRuntimeHash runtimeHash, ITypeFinderConfig typeFinderConfig = null)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_assemblyProvider = assemblyProvider;
|
||||
_runtimeHash = runtimeHash;
|
||||
_assembliesAcceptingLoadExceptions = typeFinderConfig?.AssembliesAcceptingLoadExceptions.Where(x => !x.IsNullOrWhiteSpace()).ToArray() ?? Array.Empty<string>();
|
||||
}
|
||||
|
||||
@@ -208,6 +210,9 @@ namespace Umbraco.Core.Composing
|
||||
return GetClassesWithAttribute(attributeType, assemblyList, onlyConcreteClasses);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetRuntimeHash() => _runtimeHash.GetHashValue();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Type for the string type name
|
||||
/// </summary>
|
||||
|
||||
@@ -14,8 +14,6 @@ using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Provides methods to find and instantiate types.
|
||||
/// </summary>
|
||||
@@ -29,7 +27,6 @@ namespace Umbraco.Core.Composing
|
||||
{
|
||||
private const string CacheKey = "umbraco-types.list";
|
||||
|
||||
private readonly IIOHelper _ioHelper;
|
||||
private readonly IAppPolicyCache _runtimeCache;
|
||||
private readonly IProfilingLogger _logger;
|
||||
|
||||
@@ -49,30 +46,29 @@ namespace Umbraco.Core.Composing
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypeLoader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="ioHelper"></param>
|
||||
/// <param name="runtimeHash"></param>
|
||||
/// <param name="typeFinder"></param>
|
||||
/// <param name="runtimeCache">The application runtime cache.</param>
|
||||
/// <param name="localTempPath">Files storage location.</param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <param name="assembliesToScan"></param>
|
||||
public TypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, IProfilingLogger logger, IEnumerable<Assembly> assembliesToScan = null)
|
||||
: this(ioHelper, typeFinder, runtimeCache, localTempPath, logger, true, assembliesToScan)
|
||||
public TypeLoader(ITypeFinder typeFinder, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, IProfilingLogger logger, IEnumerable<Assembly> assembliesToScan = null)
|
||||
: this(typeFinder, runtimeCache, localTempPath, logger, true, assembliesToScan)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypeLoader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="ioHelper"></param>
|
||||
/// <param name="runtimeHash"></param>
|
||||
/// <param name="typeFinder"></param>
|
||||
/// <param name="runtimeCache">The application runtime cache.</param>
|
||||
/// <param name="localTempPath">Files storage location.</param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <param name="detectChanges">Whether to detect changes using hashes.</param>
|
||||
/// <param name="assembliesToScan"></param>
|
||||
public TypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, IProfilingLogger logger, bool detectChanges, IEnumerable<Assembly> assembliesToScan = null)
|
||||
public TypeLoader(ITypeFinder typeFinder, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, IProfilingLogger logger, bool detectChanges, IEnumerable<Assembly> assembliesToScan = null)
|
||||
{
|
||||
TypeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder));
|
||||
_ioHelper = ioHelper;
|
||||
_runtimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache));
|
||||
_localTempPath = localTempPath;
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
@@ -124,7 +120,7 @@ namespace Umbraco.Core.Composing
|
||||
/// <para>This is for unit tests.</para>
|
||||
/// </remarks>
|
||||
// internal for tests
|
||||
public IEnumerable<Assembly> AssembliesToScan => _assemblies ?? (_assemblies = TypeFinder.AssembliesToScan);
|
||||
public IEnumerable<Assembly> AssembliesToScan => _assemblies ??= TypeFinder.AssembliesToScan;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type lists.
|
||||
@@ -183,19 +179,7 @@ namespace Umbraco.Core.Composing
|
||||
if (_currentAssembliesHash != null)
|
||||
return _currentAssembliesHash;
|
||||
|
||||
_currentAssembliesHash = GetFileHash(new List<Tuple<FileSystemInfo, bool>>
|
||||
{
|
||||
// TODO: Would be nicer to abstract this logic out into IAssemblyHash
|
||||
|
||||
// TODO: Use constants from SystemDirectories when we can (once it's ported to netstandard lib)
|
||||
|
||||
// the bin folder and everything in it
|
||||
new Tuple<FileSystemInfo, bool>(new DirectoryInfo(_ioHelper.MapPath("~/bin")), false),
|
||||
// the app code folder and everything in it
|
||||
new Tuple<FileSystemInfo, bool>(new DirectoryInfo(_ioHelper.MapPath("~/App_Code")), false),
|
||||
// global.asax (the app domain also monitors this, if it changes will do a full restart)
|
||||
new Tuple<FileSystemInfo, bool>(new FileInfo(_ioHelper.MapPath("~/global.asax")), false)
|
||||
}, _logger);
|
||||
_currentAssembliesHash = TypeFinder.GetRuntimeHash();
|
||||
|
||||
return _currentAssembliesHash;
|
||||
}
|
||||
@@ -210,92 +194,6 @@ namespace Umbraco.Core.Composing
|
||||
File.WriteAllText(typesHashFilePath, CurrentAssembliesHash, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a unique hash for a combination of FileInfo objects.
|
||||
/// </summary>
|
||||
/// <param name="filesAndFolders">A collection of files.</param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <returns>The hash.</returns>
|
||||
/// <remarks>Each file is a tuple containing the FileInfo object and a boolean which indicates whether to hash the
|
||||
/// file properties (false) or the file contents (true).</remarks>
|
||||
private static string GetFileHash(IEnumerable<Tuple<FileSystemInfo, bool>> filesAndFolders, IProfilingLogger logger)
|
||||
{
|
||||
using (logger.DebugDuration<TypeLoader>("Determining hash of code files on disk", "Hash determined"))
|
||||
{
|
||||
// get the distinct file infos to hash
|
||||
var uniqInfos = new HashSet<string>();
|
||||
var uniqContent = new HashSet<string>();
|
||||
using (var generator = new HashGenerator())
|
||||
{
|
||||
foreach (var fileOrFolder in filesAndFolders)
|
||||
{
|
||||
var info = fileOrFolder.Item1;
|
||||
if (fileOrFolder.Item2)
|
||||
{
|
||||
// add each unique file's contents to the hash
|
||||
// normalize the content for cr/lf and case-sensitivity
|
||||
if (uniqContent.Add(info.FullName))
|
||||
{
|
||||
if (File.Exists(info.FullName) == false) continue;
|
||||
var content = RemoveCrLf(File.ReadAllText(info.FullName));
|
||||
generator.AddCaseInsensitiveString(content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add each unique folder/file to the hash
|
||||
if (uniqInfos.Add(info.FullName))
|
||||
{
|
||||
generator.AddFileSystemItem(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
return generator.GenerateHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fast! (yes, according to benchmarks)
|
||||
private static string RemoveCrLf(string s)
|
||||
{
|
||||
var buffer = new char[s.Length];
|
||||
var count = 0;
|
||||
// ReSharper disable once ForCanBeConvertedToForeach - no!
|
||||
for (var i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (s[i] != '\r' && s[i] != '\n')
|
||||
buffer[count++] = s[i];
|
||||
}
|
||||
return new string(buffer, 0, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a unique hash for a combination of FileInfo objects.
|
||||
/// </summary>
|
||||
/// <param name="filesAndFolders">A collection of files.</param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <returns>The hash.</returns>
|
||||
// internal for tests
|
||||
public static string GetFileHash(IEnumerable<FileSystemInfo> filesAndFolders, IProfilingLogger logger)
|
||||
{
|
||||
using (logger.DebugDuration<TypeLoader>("Determining hash of code files on disk", "Hash determined"))
|
||||
{
|
||||
using (var generator = new HashGenerator())
|
||||
{
|
||||
// get the distinct file infos to hash
|
||||
var uniqInfos = new HashSet<string>();
|
||||
|
||||
foreach (var fileOrFolder in filesAndFolders)
|
||||
{
|
||||
if (uniqInfos.Contains(fileOrFolder.FullName)) continue;
|
||||
uniqInfos.Add(fileOrFolder.FullName);
|
||||
generator.AddFileSystemItem(fileOrFolder);
|
||||
}
|
||||
return generator.GenerateHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cache
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// A runtime hash this is always different on each app startup
|
||||
/// </summary>
|
||||
public sealed class VaryingRuntimeHash : IRuntimeHash
|
||||
{
|
||||
private readonly string _hash;
|
||||
|
||||
public VaryingRuntimeHash()
|
||||
{
|
||||
_hash = DateTime.Now.Ticks.ToString();
|
||||
}
|
||||
|
||||
public string GetHashValue() => _hash;
|
||||
}
|
||||
}
|
||||
@@ -20,11 +20,6 @@
|
||||
/// <value>The reserved paths.</value>
|
||||
string ReservedPaths { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to umbraco's root directory.
|
||||
/// </summary>
|
||||
string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance.
|
||||
/// </summary>
|
||||
@@ -61,6 +56,9 @@
|
||||
/// <value>The version check period in days (0 = never).</value>
|
||||
int VersionCheckPeriod { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to umbraco's root directory.
|
||||
/// </summary>
|
||||
string UmbracoPath { get; }
|
||||
string UmbracoCssPath { get; }
|
||||
string UmbracoScriptsPath { get; }
|
||||
|
||||
@@ -41,32 +41,27 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Gets the path to umbraco's root directory (/umbraco by default).
|
||||
/// </summary>
|
||||
public const string Path = "Umbraco.Core.Path";
|
||||
public const string UmbracoPath = "Umbraco.Core.Path";
|
||||
|
||||
/// <summary>
|
||||
/// The reserved urls from web.config.
|
||||
/// </summary>
|
||||
public const string ReservedUrls = "Umbraco.Core.ReservedUrls";
|
||||
|
||||
/// <summary>
|
||||
/// The path of backoffice.
|
||||
/// </summary>
|
||||
public const string UmbracoPath = "umbracoPath";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of the stylesheet folder.
|
||||
/// </summary>
|
||||
public const string UmbracoCssPath = "umbracoCssPath";
|
||||
public const string UmbracoCssPath = "Umbraco.Web.CssPath";
|
||||
|
||||
/// <summary>
|
||||
/// The path of script folder.
|
||||
/// </summary>
|
||||
public const string UmbracoScriptsPath = "umbracoScriptsPath";
|
||||
public const string UmbracoScriptsPath = "Umbraco.Core.ScriptsPath";
|
||||
|
||||
/// <summary>
|
||||
/// The path of media folder.
|
||||
/// </summary>
|
||||
public const string UmbracoMediaPath = "umbracoMediaPath";
|
||||
public const string UmbracoMediaPath = "Umbraco.Core.MediaPath";
|
||||
|
||||
/// <summary>
|
||||
/// The reserved paths from web.config
|
||||
|
||||
@@ -18,6 +18,21 @@ namespace Umbraco.Core.Hosting
|
||||
bool IsHosted { get; }
|
||||
Version IISVersion { get; }
|
||||
string MapPath(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Maps a virtual path to the application's web root
|
||||
/// </summary>
|
||||
/// <param name="virtualPath">The virtual path. Must start with either ~/ or / else an exception is thrown.</param>
|
||||
/// <param name="root">The absolute web root value. Must start with / else an exception is thrown.</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This maps the virtual path syntax to the web root. For example when hosting in a virtual directory called "site" and the value "~/pages/test" is passed in, it will
|
||||
/// map to "/site/pages/test" where "/site" is the value of root.
|
||||
/// </remarks>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// If virtualPath does not start with ~/ or /
|
||||
/// If root does not start with /
|
||||
/// </exception>
|
||||
string ToAbsolute(string virtualPath, string root);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
get
|
||||
{
|
||||
var path = _globalSettings.Path;
|
||||
var path = _globalSettings.UmbracoPath;
|
||||
|
||||
return string.IsNullOrEmpty(path) ? string.Empty : ResolveUrl(path);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace Umbraco.Core.Runtime
|
||||
var databaseFactory = GetDatabaseFactory();
|
||||
|
||||
// type finder/loader
|
||||
var typeLoader = new TypeLoader(IOHelper, TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), ProfilingLogger);
|
||||
var typeLoader = new TypeLoader(TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), ProfilingLogger);
|
||||
|
||||
// create the composition
|
||||
composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches);
|
||||
|
||||
@@ -15,16 +15,18 @@ namespace Umbraco.Tests.Benchmarks
|
||||
[Benchmark(Baseline = true)]
|
||||
public void WithGetReferencingAssembliesCheck()
|
||||
{
|
||||
var typeFinder1 = new TypeFinder(new NullLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder1 = new TypeFinder(new NullLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash());
|
||||
var found = typeFinder1.FindClassesOfType<IDiscoverable>().Count();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void WithoutGetReferencingAssembliesCheck()
|
||||
{
|
||||
var typeFinder2 = new TypeFinder(new NullLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder2 = new TypeFinder(new NullLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash());
|
||||
typeFinder2.QueryWithReferencingAssemblies = false;
|
||||
var found = typeFinder2.FindClassesOfType<IDiscoverable>().Count();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ namespace Umbraco.Tests.Common
|
||||
settings.ConfigurationStatus == semanticVersion.ToSemanticString() &&
|
||||
settings.UseHttps == false &&
|
||||
settings.HideTopLevelNodeFromPath == false &&
|
||||
settings.Path == "~/umbraco" &&
|
||||
settings.TimeOutInMinutes == 20 &&
|
||||
settings.DefaultUILanguage == "en" &&
|
||||
settings.ReservedPaths == (GlobalSettings.StaticReservedPaths + "~/umbraco") &&
|
||||
|
||||
@@ -36,14 +36,14 @@ namespace Umbraco.Tests.Common
|
||||
{
|
||||
SettingsForTests = new SettingsForTests();
|
||||
MainDom = new SimpleMainDom();
|
||||
_typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(entryAssembly));
|
||||
_typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(entryAssembly), new VaryingRuntimeHash());
|
||||
}
|
||||
|
||||
public ITypeFinder GetTypeFinder() => _typeFinder;
|
||||
|
||||
public TypeLoader GetMockedTypeLoader()
|
||||
{
|
||||
return new TypeLoader(IOHelper, Mock.Of<ITypeFinder>(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(IOHelper.MapPath("~/App_Data/TEMP")), Mock.Of<IProfilingLogger>());
|
||||
return new TypeLoader(Mock.Of<ITypeFinder>(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(IOHelper.MapPath("~/App_Data/TEMP")), Mock.Of<IProfilingLogger>());
|
||||
}
|
||||
|
||||
public Configs GetConfigs() => GetConfigsFactory().Create();
|
||||
|
||||
@@ -106,8 +106,7 @@ namespace Umbraco.Tests.Integration.Implementations
|
||||
public override IHostingEnvironment GetHostingEnvironment()
|
||||
=> _hostingEnvironment ??= new TestHostingEnvironment(
|
||||
SettingsForTests.GetDefaultHostingSettings(),
|
||||
_hostEnvironment,
|
||||
_httpContextAccessor);
|
||||
_hostEnvironment);
|
||||
|
||||
public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _hostingLifetime;
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace Umbraco.Tests.Integration.Implementations
|
||||
|
||||
public class TestHostingEnvironment : AspNetCoreHostingEnvironment, Umbraco.Core.Hosting.IHostingEnvironment
|
||||
{
|
||||
public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor)
|
||||
: base(hostingSettings, webHostEnvironment, httpContextAccessor)
|
||||
public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment)
|
||||
: base(hostingSettings, webHostEnvironment)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Umbraco.Tests.Components
|
||||
private static TypeLoader MockTypeLoader()
|
||||
{
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
return new TypeLoader(ioHelper, Mock.Of<ITypeFinder>(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), Mock.Of<IProfilingLogger>());
|
||||
return new TypeLoader(Mock.Of<ITypeFinder>(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), Mock.Of<IProfilingLogger>());
|
||||
}
|
||||
|
||||
public static IRuntimeState MockRuntimeState(RuntimeLevel level)
|
||||
@@ -372,7 +372,7 @@ namespace Umbraco.Tests.Components
|
||||
{
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), Mock.Of<IProfilingLogger>());
|
||||
var typeLoader = new TypeLoader(typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), Mock.Of<IProfilingLogger>());
|
||||
|
||||
var register = MockRegister();
|
||||
var composition = new Composition(register, typeLoader, Mock.Of<IProfilingLogger>(),
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Composing
|
||||
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
TypeLoader = new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), ProfilingLogger, false, AssembliesToScan);
|
||||
TypeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), ProfilingLogger, false, AssembliesToScan);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.Composing
|
||||
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, Mock.Of<IAppPolicyCache>(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), logger);
|
||||
var typeLoader = new TypeLoader(typeFinder, Mock.Of<IAppPolicyCache>(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), logger);
|
||||
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of<IRuntimeState>(), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache);
|
||||
|
||||
// create the factory, ensure it is the mocked factory
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Tests.Composing
|
||||
[Test]
|
||||
public void Find_Class_Of_Type_With_Attribute()
|
||||
{
|
||||
var typeFinder = new TypeFinder(GetTestProfilingLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = new TypeFinder(GetTestProfilingLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash());
|
||||
var typesFound = typeFinder.FindClassesOfTypeWithAttribute<TestEditor, MyTestAttribute>(_assemblies);
|
||||
Assert.AreEqual(2, typesFound.Count());
|
||||
}
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Tests.Composing
|
||||
[Test]
|
||||
public void Find_Classes_With_Attribute()
|
||||
{
|
||||
var typeFinder = new TypeFinder(GetTestProfilingLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = new TypeFinder(GetTestProfilingLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash());
|
||||
var typesFound = typeFinder.FindClassesWithAttribute<TreeAttribute>(_assemblies);
|
||||
Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree]
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Tests.Composing
|
||||
{
|
||||
// this ensures it's reset
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
_typeLoader = new TypeLoader(TestHelper.IOHelper, typeFinder, NoAppCache.Instance,
|
||||
_typeLoader = new TypeLoader(typeFinder, NoAppCache.Instance,
|
||||
new DirectoryInfo(TestHelper.IOHelper.MapPath("~/App_Data/TEMP")),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()), false,
|
||||
|
||||
@@ -217,7 +217,7 @@ AnotherContentFinder
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Plugins_Hash()
|
||||
public void Get_Plugins_Hash_With_Hash_Generator()
|
||||
{
|
||||
//Arrange
|
||||
var dir = PrepareFolder();
|
||||
@@ -244,16 +244,16 @@ AnotherContentFinder
|
||||
var list3 = new[] { f1, f3, f5, f7 };
|
||||
|
||||
//Act
|
||||
var hash1 = TypeLoader.GetFileHash(list1, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var hash2 = TypeLoader.GetFileHash(list2, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var hash3 = TypeLoader.GetFileHash(list3, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var hash1 = GetFileHash(list1, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var hash2 = GetFileHash(list2, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var hash3 = GetFileHash(list3, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
//Assert
|
||||
Assert.AreNotEqual(hash1, hash2);
|
||||
Assert.AreNotEqual(hash1, hash3);
|
||||
Assert.AreNotEqual(hash2, hash3);
|
||||
|
||||
Assert.AreEqual(hash1, TypeLoader.GetFileHash(list1, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
|
||||
Assert.AreEqual(hash1, GetFileHash(list1, new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -316,5 +316,32 @@ AnotherContentFinder
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a unique hash for a combination of FileInfo objects.
|
||||
/// </summary>
|
||||
/// <param name="filesAndFolders">A collection of files.</param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <returns>The hash.</returns>
|
||||
// internal for tests
|
||||
private static string GetFileHash(IEnumerable<FileSystemInfo> filesAndFolders, IProfilingLogger logger)
|
||||
{
|
||||
using (logger.DebugDuration<TypeLoader>("Determining hash of code files on disk", "Hash determined"))
|
||||
{
|
||||
using (var generator = new HashGenerator())
|
||||
{
|
||||
// get the distinct file infos to hash
|
||||
var uniqInfos = new HashSet<string>();
|
||||
|
||||
foreach (var fileOrFolder in filesAndFolders)
|
||||
{
|
||||
if (uniqInfos.Contains(fileOrFolder.FullName)) continue;
|
||||
uniqInfos.Add(fileOrFolder.FullName);
|
||||
generator.AddFileSystemItem(fileOrFolder);
|
||||
}
|
||||
return generator.GenerateHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Tests.Configurations
|
||||
var ioHelper = new IOHelper(TestHelper.GetHostingEnvironment(), globalSettings);
|
||||
|
||||
var globalSettingsMock = Mock.Get(globalSettings);
|
||||
globalSettingsMock.Setup(x => x.Path).Returns(() => path);
|
||||
globalSettingsMock.Setup(x => x.UmbracoPath).Returns(() => path);
|
||||
|
||||
ioHelper.Root = rootPath;
|
||||
Assert.AreEqual(outcome, ioHelper.GetUmbracoMvcAreaNoCache());
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
var baseLoader = base.CreateTypeLoader(ioHelper, typeFinder, runtimeCache, logger, hostingEnvironment);
|
||||
|
||||
return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(hostingEnvironment.LocalTempPath), logger, false,
|
||||
return new TypeLoader(typeFinder, runtimeCache, new DirectoryInfo(hostingEnvironment.LocalTempPath), logger, false,
|
||||
// this is so the model factory looks into the test assembly
|
||||
baseLoader.AssembliesToScan
|
||||
.Union(new[] {typeof(PublishedContentMoreTests).Assembly})
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
var baseLoader = base.CreateTypeLoader(ioHelper, typeFinder, runtimeCache, logger, hostingEnvironment);
|
||||
|
||||
return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(hostingEnvironment.LocalTempPath), logger, false,
|
||||
return new TypeLoader(typeFinder, runtimeCache, new DirectoryInfo(hostingEnvironment.LocalTempPath), logger, false,
|
||||
// this is so the model factory looks into the test assembly
|
||||
baseLoader.AssembliesToScan
|
||||
.Union(new[] { typeof(PublishedContentTests).Assembly })
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
var databaseFactory = new UmbracoDatabaseFactory(logger,globalSettings, connectionStrings, new Lazy<IMapperCollection>(() => factory.GetInstance<IMapperCollection>()), TestHelper.DbProviderFactoryCreator);
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var hostingEnvironment = Mock.Of<IHostingEnvironment>();
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), profilingLogger);
|
||||
var typeLoader = new TypeLoader(typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), profilingLogger);
|
||||
var mainDom = new SimpleMainDom();
|
||||
var umbracoVersion = TestHelper.GetUmbracoVersion();
|
||||
var backOfficeInfo = TestHelper.GetBackOfficeInfo();
|
||||
@@ -262,7 +262,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
var databaseFactory = Mock.Of<IUmbracoDatabaseFactory>();
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), profilingLogger);
|
||||
var typeLoader = new TypeLoader(typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), profilingLogger);
|
||||
var runtimeState = Mock.Of<IRuntimeState>();
|
||||
var hostingEnvironment = Mock.Of<IHostingEnvironment>();
|
||||
var backOfficeInfo = TestHelper.GetBackOfficeInfo();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance,
|
||||
var typeLoader = new TypeLoader(typeFinder, NoAppCache.Instance,
|
||||
new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")),
|
||||
logger,
|
||||
false);
|
||||
|
||||
@@ -253,7 +253,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
TestHelper.DbProviderFactoryCreator);
|
||||
}
|
||||
|
||||
typeFinder ??= new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
typeFinder ??= new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash());
|
||||
fileSystems ??= new FileSystems(Current.Factory, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings());
|
||||
var coreDebug = TestHelper.CoreDebugSettings;
|
||||
var mediaFileSystem = Mock.Of<IMediaFileSystem>();
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Umbraco.Tests.Testing
|
||||
var proflogger = new ProfilingLogger(logger, profiler);
|
||||
IOHelper = TestHelper.IOHelper;
|
||||
|
||||
TypeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
TypeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash());
|
||||
var appCaches = GetAppCaches();
|
||||
var globalSettings = TestHelpers.SettingsForTests.GetDefaultGlobalSettings();
|
||||
var settings = TestHelpers.SettingsForTests.GenerateMockWebRoutingSettings();
|
||||
@@ -376,7 +376,7 @@ namespace Umbraco.Tests.Testing
|
||||
switch (option)
|
||||
{
|
||||
case UmbracoTestOptions.TypeLoader.Default:
|
||||
return _commonTypeLoader ?? (_commonTypeLoader = CreateCommonTypeLoader(ioHelper, typeFinder, runtimeCache, logger, hostingEnvironment));
|
||||
return _commonTypeLoader ?? (_commonTypeLoader = CreateCommonTypeLoader(typeFinder, runtimeCache, logger, hostingEnvironment));
|
||||
case UmbracoTestOptions.TypeLoader.PerFixture:
|
||||
return _featureTypeLoader ?? (_featureTypeLoader = CreateTypeLoader(ioHelper, typeFinder, runtimeCache, logger, hostingEnvironment));
|
||||
case UmbracoTestOptions.TypeLoader.PerTest:
|
||||
@@ -388,13 +388,13 @@ namespace Umbraco.Tests.Testing
|
||||
|
||||
protected virtual TypeLoader CreateTypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, IProfilingLogger logger, IHostingEnvironment hostingEnvironment)
|
||||
{
|
||||
return CreateCommonTypeLoader(ioHelper, typeFinder, runtimeCache, logger, hostingEnvironment);
|
||||
return CreateCommonTypeLoader(typeFinder, runtimeCache, logger, hostingEnvironment);
|
||||
}
|
||||
|
||||
// common to all tests = cannot be overriden
|
||||
private static TypeLoader CreateCommonTypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, IProfilingLogger logger, IHostingEnvironment hostingEnvironment)
|
||||
private static TypeLoader CreateCommonTypeLoader(ITypeFinder typeFinder, IAppPolicyCache runtimeCache, IProfilingLogger logger, IHostingEnvironment hostingEnvironment)
|
||||
{
|
||||
return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(hostingEnvironment.LocalTempPath), logger, false, new[]
|
||||
return new TypeLoader(typeFinder, runtimeCache, new DirectoryInfo(hostingEnvironment.LocalTempPath), logger, false, new[]
|
||||
{
|
||||
Assembly.Load("Umbraco.Core"),
|
||||
Assembly.Load("Umbraco.Web"),
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace Umbraco.Tests.Web
|
||||
container
|
||||
.Setup(x => x.GetInstance(typeof(TypeLoader)))
|
||||
.Returns(new TypeLoader(
|
||||
ioHelper,
|
||||
typeFinder,
|
||||
NoAppCache.Instance,
|
||||
new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -100,10 +101,6 @@ namespace Umbraco.Web.Common.Extensions
|
||||
var globalSettings = configs.Global();
|
||||
var umbracoVersion = new UmbracoVersion(globalSettings);
|
||||
|
||||
// TODO: Currently we are not passing in any TypeFinderConfig (with ITypeFinderSettings) which we should do, however
|
||||
// this is not critical right now and would require loading in some config before boot time so just leaving this as-is for now.
|
||||
var typeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(entryAssembly));
|
||||
|
||||
var coreRuntime = GetCoreRuntime(
|
||||
configs,
|
||||
umbracoVersion,
|
||||
@@ -112,13 +109,23 @@ namespace Umbraco.Web.Common.Extensions
|
||||
profiler,
|
||||
hostingEnvironment,
|
||||
backOfficeInfo,
|
||||
typeFinder);
|
||||
CreateTypeFinder(logger, profiler, webHostEnvironment, entryAssembly));
|
||||
|
||||
factory = coreRuntime.Configure(container);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static ITypeFinder CreateTypeFinder(ILogger logger, IProfiler profiler, IWebHostEnvironment webHostEnvironment, Assembly entryAssembly)
|
||||
{
|
||||
// TODO: Currently we are not passing in any TypeFinderConfig (with ITypeFinderSettings) which we should do, however
|
||||
// this is not critical right now and would require loading in some config before boot time so just leaving this as-is for now.
|
||||
var runtimeHashPaths = new RuntimeHashPaths();
|
||||
runtimeHashPaths.AddFolder(new DirectoryInfo(Path.Combine(webHostEnvironment.ContentRootPath, "bin")));
|
||||
var runtimeHash = new RuntimeHash(new ProfilingLogger(logger, profiler), runtimeHashPaths);
|
||||
return new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(entryAssembly), runtimeHash);
|
||||
}
|
||||
|
||||
private static IRuntime GetCoreRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger,
|
||||
IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo,
|
||||
ITypeFinder typeFinder)
|
||||
@@ -161,7 +168,7 @@ namespace Umbraco.Web.Common.Extensions
|
||||
var coreDebug = configs.CoreDebug();
|
||||
var globalSettings = configs.Global();
|
||||
|
||||
hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor);
|
||||
hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment);
|
||||
ioHelper = new IOHelper(hostingEnvironment, globalSettings);
|
||||
logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment,
|
||||
new AspNetCoreSessionIdResolver(httpContextAccessor),
|
||||
|
||||
@@ -9,7 +9,8 @@ namespace Umbraco.Web.Common.RuntimeMinification
|
||||
{
|
||||
public void Compose(Composition composition)
|
||||
{
|
||||
composition.Register<IRuntimeMinifier, SmidgeRuntimeMinifier>(Core.Composing.Lifetime.Scope);
|
||||
composition.RegisterUnique<IRuntimeMinifier, SmidgeRuntimeMinifier>();
|
||||
composition.RegisterUnique<SmidgeHelperAccessor>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Smidge;
|
||||
|
||||
namespace Umbraco.Web.Common.RuntimeMinification
|
||||
{
|
||||
// work around for SmidgeHelper being request/scope lifetime
|
||||
public sealed class SmidgeHelperAccessor
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public SmidgeHelperAccessor(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public SmidgeHelper SmidgeHelper
|
||||
{
|
||||
get
|
||||
{
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null)
|
||||
throw new InvalidOperationException($"Cannot get a {nameof(SmidgeHelper)} instance since there is no current http request");
|
||||
return httpContext.RequestServices.GetService<SmidgeHelper>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,15 @@ namespace Umbraco.Web.Common.RuntimeMinification
|
||||
private readonly ISmidgeConfig _smidgeConfig;
|
||||
private readonly IConfigManipulator _configManipulator;
|
||||
private readonly PreProcessPipelineFactory _preProcessPipelineFactory;
|
||||
private readonly BundleManager _bundles;
|
||||
private readonly SmidgeHelper _smidge;
|
||||
private readonly IBundleManager _bundles;
|
||||
private readonly SmidgeHelperAccessor _smidge;
|
||||
|
||||
private PreProcessPipeline _jsPipeline;
|
||||
private PreProcessPipeline _cssPipeline;
|
||||
|
||||
public SmidgeRuntimeMinifier(
|
||||
BundleManager bundles,
|
||||
SmidgeHelper smidge,
|
||||
IBundleManager bundles,
|
||||
SmidgeHelperAccessor smidge,
|
||||
PreProcessPipelineFactory preProcessPipelineFactory,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
ISmidgeConfig smidgeConfig,
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Web.Common.RuntimeMinification
|
||||
// affect this or vice versa.
|
||||
}
|
||||
|
||||
public string RenderCssHere(string bundleName) => _smidge.CssHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
|
||||
public string RenderCssHere(string bundleName) => _smidge.SmidgeHelper.CssHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
|
||||
|
||||
public void CreateJsBundle(string bundleName, params string[] filePaths)
|
||||
{
|
||||
@@ -82,9 +82,9 @@ namespace Umbraco.Web.Common.RuntimeMinification
|
||||
// affect this or vice versa.
|
||||
}
|
||||
|
||||
public string RenderJsHere(string bundleName) => _smidge.JsHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
|
||||
public string RenderJsHere(string bundleName) => _smidge.SmidgeHelper.JsHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
|
||||
|
||||
public async Task<IEnumerable<string>> GetAssetPathsAsync(string bundleName) => await _smidge.GenerateJsUrlsAsync(bundleName, _hostingEnvironment.IsDebugMode);
|
||||
public async Task<IEnumerable<string>> GetAssetPathsAsync(string bundleName) => await _smidge.SmidgeHelper.GenerateJsUrlsAsync(bundleName, _hostingEnvironment.IsDebugMode);
|
||||
|
||||
public async Task<string> MinifyAsync(string fileContent, AssetType assetType)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Web.UI.BackOffice
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
/// <summary>
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Web.UI.BackOffice
|
||||
/// </remarks>
|
||||
public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config)
|
||||
{
|
||||
_webHostEnvironment = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment));
|
||||
_env = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment));
|
||||
_config = config ?? throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Web.UI.BackOffice
|
||||
{
|
||||
services.AddUmbracoConfiguration(_config);
|
||||
services.AddUmbracoRuntimeMinifier(_config);
|
||||
services.AddUmbracoCore(_webHostEnvironment, out var factory);
|
||||
services.AddUmbracoCore(_env, out var factory);
|
||||
services.AddUmbracoWebsite();
|
||||
|
||||
services.AddMvc();
|
||||
@@ -66,12 +66,12 @@ namespace Umbraco.Web.UI.BackOffice
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
|
||||
// app.UseMiniProfiler();
|
||||
app.UseUmbracoRequest();
|
||||
if (env.IsDevelopment())
|
||||
if (_env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
@@ -80,9 +81,18 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual ITypeFinder GetTypeFinder()
|
||||
{
|
||||
// TODO: Currently we are not passing in any TypeFinderConfig (with ITypeFinderSettings) which we should do, however
|
||||
// this is not critical right now and would require loading in some config before boot time so just leaving this as-is for now.
|
||||
=> new TypeFinder(Logger, new DefaultUmbracoAssemblyProvider(
|
||||
var runtimeHashPaths = new RuntimeHashPaths();
|
||||
// the bin folder and everything in it
|
||||
runtimeHashPaths.AddFolder(new DirectoryInfo(Current.IOHelper.MapPath("~/bin")));
|
||||
// the app code folder and everything in it
|
||||
runtimeHashPaths.AddFile(new FileInfo(Current.IOHelper.MapPath("~/App_Code")));
|
||||
// global.asax (the app domain also monitors this, if it changes will do a full restart)
|
||||
runtimeHashPaths.AddFile(new FileInfo(Current.IOHelper.MapPath("~/global.asax")));
|
||||
var runtimeHash = new RuntimeHash(new ProfilingLogger(Current.Logger, Current.Profiler), runtimeHashPaths);
|
||||
return new TypeFinder(Logger, new DefaultUmbracoAssemblyProvider(
|
||||
// GetEntryAssembly was actually an exposed API by request of the aspnetcore team which works in aspnet core because a website
|
||||
// in that case is essentially an exe. However in netframework there is no entry assembly, things don't really work that way since
|
||||
// the process that is running the site is iisexpress, so this returns null. The best we can do is fallback to GetExecutingAssembly()
|
||||
@@ -94,7 +104,8 @@ namespace Umbraco.Web
|
||||
// assembly we can get and we can only get that if we put this code into the WebRuntime since the executing assembly is the 'current' one.
|
||||
// For this purpose, it doesn't matter if it's Umbraco.Web or Umbraco.Infrastructure since all assemblies are in that same path and we are
|
||||
// getting rid of netframework.
|
||||
Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly()));
|
||||
Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly()), runtimeHash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a runtime.
|
||||
|
||||
Reference in New Issue
Block a user