Fixes typefinder/loader dependency refs, allows config to specify additional entry assemblies

This commit is contained in:
Shannon
2021-07-09 16:15:37 -06:00
parent 7ec3afa5ff
commit f7b8a93a35
16 changed files with 127 additions and 87 deletions

View File

@@ -17,12 +17,17 @@ namespace Umbraco.Cms.Core.Composing
{
private readonly Assembly _entryPointAssembly;
private readonly ILoggerFactory _loggerFactory;
private readonly IEnumerable<string> _additionalTargetAssemblies;
private List<Assembly> _discovered;
public DefaultUmbracoAssemblyProvider(Assembly entryPointAssembly, ILoggerFactory loggerFactory)
public DefaultUmbracoAssemblyProvider(
Assembly entryPointAssembly,
ILoggerFactory loggerFactory,
IEnumerable<string> additionalTargetAssemblies = null)
{
_entryPointAssembly = entryPointAssembly ?? throw new ArgumentNullException(nameof(entryPointAssembly));
_loggerFactory = loggerFactory;
_additionalTargetAssemblies = additionalTargetAssemblies;
}
// TODO: It would be worth investigating a netcore3 version of this which would use
@@ -40,7 +45,9 @@ namespace Umbraco.Cms.Core.Composing
return _discovered;
}
var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, Constants.Composing.UmbracoCoreAssemblyNames, true, _loggerFactory);
IEnumerable<string> additionalTargetAssemblies = _additionalTargetAssemblies.Concat(Constants.Composing.UmbracoCoreAssemblyNames);
var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, additionalTargetAssemblies.ToArray(), true, _loggerFactory);
_discovered = finder.Find().ToList();
return _discovered;

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -18,6 +18,7 @@ namespace Umbraco.Cms.Core.Composing
private readonly string[] _targetAssemblies;
private readonly bool _includeTargets;
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger<FindAssembliesWithReferencesTo> _logger;
/// <summary>
/// Constructor
@@ -32,6 +33,7 @@ namespace Umbraco.Cms.Core.Composing
_targetAssemblies = targetAssemblyNames;
_includeTargets = includeTargets;
_loggerFactory = loggerFactory;
_logger = _loggerFactory.CreateLogger<FindAssembliesWithReferencesTo>();
}
public IEnumerable<Assembly> Find()
@@ -50,9 +52,10 @@ namespace Umbraco.Cms.Core.Composing
{
referenceItems.Add(Assembly.Load(target));
}
catch (FileNotFoundException)
catch (FileNotFoundException ex)
{
// occurs if we cannot load this ... for example in a test project where we aren't currently referencing Umbraco.Web, etc...
_logger.LogDebug(ex, "Could not load assembly " + target);
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -51,14 +51,5 @@ namespace Umbraco.Cms.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();
}
}

View File

@@ -17,7 +17,6 @@ namespace Umbraco.Cms.Core.Composing
{
private readonly ILogger<TypeFinder> _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>();
@@ -27,13 +26,12 @@ namespace Umbraco.Cms.Core.Composing
// used for benchmark tests
internal bool QueryWithReferencingAssemblies { get; set; } = true;
public TypeFinder(ILogger<TypeFinder> logger, IAssemblyProvider assemblyProvider, IRuntimeHash runtimeHash, ITypeFinderConfig typeFinderConfig = null)
public TypeFinder(ILogger<TypeFinder> logger, IAssemblyProvider assemblyProvider, ITypeFinderConfig typeFinderConfig = null)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_assemblyProvider = assemblyProvider;
_runtimeHash = runtimeHash;
_typeFinderConfig = typeFinderConfig;
}
}
private string[] _assembliesAcceptingLoadExceptions = null;
@@ -64,9 +62,12 @@ namespace Umbraco.Cms.Core.Composing
var name = a.GetName().Name; // simple name of the assembly
return AssembliesAcceptingLoadExceptions.Any(pattern =>
{
if (pattern.Length > name.Length) return false; // pattern longer than name
if (pattern.Length == name.Length) return pattern.InvariantEquals(name); // same length, must be identical
if (pattern[pattern.Length] != '.') return false; // pattern is shorter than name, must end with dot
if (pattern.Length > name.Length)
return false; // pattern longer than name
if (pattern.Length == name.Length)
return pattern.InvariantEquals(name); // same length, must be identical
if (pattern[pattern.Length] != '.')
return false; // pattern is shorter than name, must end with dot
return name.StartsWith(pattern); // and name must start with pattern
});
}
@@ -112,6 +113,8 @@ namespace Umbraco.Cms.Core.Composing
&& exclusionFilter.Any(f => x.FullName.StartsWith(f)) == false);
}
// TODO: Kill this
/// <summary>
/// this is our assembly filter to filter out known types that def don't contain types we'd like to find or plugins
/// </summary>
@@ -232,9 +235,6 @@ namespace Umbraco.Cms.Core.Composing
return GetClassesWithAttribute(attributeType, assemblyList, onlyConcreteClasses);
}
/// <inheritdoc />
public string GetRuntimeHash() => _runtimeHash.GetHashValue();
/// <summary>
/// Returns a Type for the string type name
/// </summary>
@@ -455,7 +455,8 @@ namespace Umbraco.Cms.Core.Composing
var ex = new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
// rethrow with new message, unless accepted
if (AcceptsLoadExceptions(a) == false) throw ex;
if (AcceptsLoadExceptions(a) == false)
throw ex;
// log a warning, and return what we can
lock (_notifiedLoadExceptionAssemblies)

View File

@@ -1,6 +1,7 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Configuration.UmbracoSettings;
@@ -15,17 +16,16 @@ namespace Umbraco.Cms.Core.Composing
private readonly TypeFinderSettings _settings;
private IEnumerable<string> _assembliesAcceptingLoadExceptions;
public TypeFinderConfig(IOptions<TypeFinderSettings> settings)
{
_settings = settings.Value;
}
public TypeFinderConfig(IOptions<TypeFinderSettings> settings) => _settings = settings.Value;
public IEnumerable<string> AssembliesAcceptingLoadExceptions
{
get
{
if (_assembliesAcceptingLoadExceptions != null)
{
return _assembliesAcceptingLoadExceptions;
}
var s = _settings.AssembliesAcceptingLoadExceptions;
return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s)

View File

@@ -25,9 +25,8 @@ namespace Umbraco.Cms.Core.Composing
/// on a hash of the DLLs in the ~/bin folder to check for cache expiration.</para>
/// </remarks>
public sealed class TypeLoader
{
internal const string CacheKey = "umbraco-types.list";
{
private readonly IRuntimeHash _runtimeHash;
private readonly IAppPolicyCache _runtimeCache;
private readonly ILogger<TypeLoader> _logger;
private readonly IProfilingLogger _profilingLogger;
@@ -44,7 +43,9 @@ namespace Umbraco.Cms.Core.Composing
private bool _reportedChange;
private readonly DirectoryInfo _localTempPath;
private readonly Lazy<string> _fileBasePath;
private readonly Dictionary<(string, string), IEnumerable<string>> EmptyCache = new Dictionary<(string, string), IEnumerable<string>>();
private readonly Dictionary<(string, string), IEnumerable<string>> _emptyCache = new Dictionary<(string, string), IEnumerable<string>>();
private string _typesListFilePath;
private string _typesHashFilePath;
/// <summary>
/// Initializes a new instance of the <see cref="TypeLoader"/> class.
@@ -54,8 +55,8 @@ namespace Umbraco.Cms.Core.Composing
/// <param name="localTempPath">Files storage location.</param>
/// <param name="logger">A profiling logger.</param>
/// <param name="assembliesToScan"></param>
public TypeLoader(ITypeFinder typeFinder, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, ILogger<TypeLoader> logger, IProfiler profiler, IEnumerable<Assembly> assembliesToScan = null)
: this(typeFinder, runtimeCache, localTempPath, logger, profiler, true, assembliesToScan)
public TypeLoader(ITypeFinder typeFinder, IRuntimeHash runtimeHash, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, ILogger<TypeLoader> logger, IProfiler profiler, IEnumerable<Assembly> assembliesToScan = null)
: this(typeFinder, runtimeHash, runtimeCache, localTempPath, logger, profiler, true, assembliesToScan)
{ }
/// <summary>
@@ -67,14 +68,18 @@ namespace Umbraco.Cms.Core.Composing
/// <param name="logger">A profiling logger.</param>
/// <param name="detectChanges">Whether to detect changes using hashes.</param>
/// <param name="assembliesToScan"></param>
public TypeLoader(ITypeFinder typeFinder, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, ILogger<TypeLoader> logger, IProfiler profiler, bool detectChanges, IEnumerable<Assembly> assembliesToScan = null)
public TypeLoader(ITypeFinder typeFinder, IRuntimeHash runtimeHash, IAppPolicyCache runtimeCache, DirectoryInfo localTempPath, ILogger<TypeLoader> logger, IProfiler profiler, bool detectChanges, IEnumerable<Assembly> assembliesToScan = null)
{
if (profiler is null)
{
throw new ArgumentNullException(nameof(profiler));
}
var runtimeHashValue = runtimeHash.GetHashValue();
CacheKey = runtimeHashValue + "umbraco-types.list";
TypeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder));
_runtimeHash = runtimeHash;
_runtimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache));
_localTempPath = localTempPath;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -119,6 +124,8 @@ namespace Umbraco.Cms.Core.Composing
}
}
internal string CacheKey { get; }
/// <summary>
/// Returns the underlying <see cref="ITypeFinder"/>
/// </summary>
@@ -202,9 +209,11 @@ namespace Umbraco.Cms.Core.Composing
get
{
if (_currentAssembliesHash != null)
{
return _currentAssembliesHash;
}
_currentAssembliesHash = TypeFinder.GetRuntimeHash();
_currentAssembliesHash = _runtimeHash.GetHashValue();
return _currentAssembliesHash;
}
@@ -268,7 +277,7 @@ namespace Umbraco.Cms.Core.Composing
}
}
return EmptyCache;
return _emptyCache;
}
// internal for tests
@@ -277,7 +286,7 @@ namespace Umbraco.Cms.Core.Composing
var typesListFilePath = GetTypesListFilePath();
if (typesListFilePath == null || File.Exists(typesListFilePath) == false)
{
return EmptyCache;
return _emptyCache;
}
var cache = new Dictionary<(string, string), IEnumerable<string>>();
@@ -332,9 +341,9 @@ namespace Umbraco.Cms.Core.Composing
}
// internal for tests
public string GetTypesListFilePath() => _fileBasePath.Value == null ? null : _fileBasePath.Value + ".list";
public string GetTypesListFilePath() => _typesListFilePath ??= _fileBasePath.Value == null ? null : _fileBasePath.Value + ".list";
private string GetTypesHashFilePath() => _fileBasePath.Value == null ? null : _fileBasePath.Value + ".hash";
private string GetTypesHashFilePath() => _typesHashFilePath ??= _fileBasePath.Value == null ? null : _fileBasePath.Value + ".hash";
/// <summary>
/// Used to produce the Lazy value of _fileBasePath

View File

@@ -1,6 +1,9 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections;
using System.Collections.Generic;
namespace Umbraco.Cms.Core.Configuration.Models
{
/// <summary>
@@ -13,5 +16,11 @@ namespace Umbraco.Cms.Core.Configuration.Models
/// Gets or sets a value for the assemblies that accept load exceptions during type finder operations.
/// </summary>
public string AssembliesAcceptingLoadExceptions { get; set; }
/// <summary>
/// By default the entry assemblies for scanning plugin types is the Umbraco DLLs. If you require
/// scanning for plugins based on different root referenced assemblies you can add the assembly name to this list.
/// </summary>
public IEnumerable<string> AdditionalEntryAssemblies { get; set; }
}
}

View File

@@ -16,8 +16,8 @@ namespace Umbraco.Tests.Benchmarks
public TypeFinderBenchmarks()
{
_typeFinder1 = new TypeFinder(new NullLogger<TypeFinder>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance), new VaryingRuntimeHash());
_typeFinder2 = new TypeFinder(new NullLogger<TypeFinder>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance), new VaryingRuntimeHash())
_typeFinder1 = new TypeFinder(new NullLogger<TypeFinder>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance));
_typeFinder2 = new TypeFinder(new NullLogger<TypeFinder>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance))
{
QueryWithReferencingAssemblies = false
};

View File

@@ -21,12 +21,12 @@ namespace Umbraco.Tests.Benchmarks
{
var typeFinder1 = new TypeFinder(
new NullLogger<TypeFinder>(),
new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance),
new VaryingRuntimeHash());
new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance));
var cache = new ObjectCacheAppCache();
_typeLoader1 = new TypeLoader(
typeFinder1,
new VaryingRuntimeHash(),
cache,
null,
new NullLogger<TypeLoader>(),
@@ -40,6 +40,7 @@ namespace Umbraco.Tests.Benchmarks
_typeLoader2 = new TypeLoader(
typeFinder1,
new VaryingRuntimeHash(),
NoAppCache.Instance,
null,
new NullLogger<TypeLoader>(),

View File

@@ -44,13 +44,13 @@ namespace Umbraco.Cms.Tests.Common
protected TestHelperBase(Assembly entryAssembly)
{
MainDom = new SimpleMainDom();
_typeFinder = new TypeFinder(NullLoggerFactory.Instance.CreateLogger<TypeFinder>(), new DefaultUmbracoAssemblyProvider(entryAssembly, NullLoggerFactory.Instance), new VaryingRuntimeHash());
_typeFinder = new TypeFinder(NullLoggerFactory.Instance.CreateLogger<TypeFinder>(), new DefaultUmbracoAssemblyProvider(entryAssembly, NullLoggerFactory.Instance));
}
public ITypeFinder GetTypeFinder() => _typeFinder;
public TypeLoader GetMockedTypeLoader() =>
new TypeLoader(Mock.Of<ITypeFinder>(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
new TypeLoader(Mock.Of<ITypeFinder>(), new VaryingRuntimeHash(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
//// public Configs GetConfigs() => GetConfigsFactory().Create();

View File

@@ -78,7 +78,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
private static IServiceCollection MockRegister() => new ServiceCollection();
private static TypeLoader MockTypeLoader() => new TypeLoader(Mock.Of<ITypeFinder>(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
private static TypeLoader MockTypeLoader() => new TypeLoader(Mock.Of<ITypeFinder>(), new VaryingRuntimeHash(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
[Test]
public void Boot1A()
@@ -438,7 +438,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
public void AllComposers()
{
ITypeFinder typeFinder = TestHelper.GetTypeFinder();
var typeLoader = new TypeLoader(typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(typeFinder, new VaryingRuntimeHash(), AppCaches.Disabled.RuntimeCache, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
IServiceCollection register = MockRegister();
var builder = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());

View File

@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Composing
public void Initialize()
{
var typeFinder = TestHelper.GetTypeFinder();
TypeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>(), false, AssembliesToScan);
TypeLoader = new TypeLoader(typeFinder, new VaryingRuntimeHash(), NoAppCache.Instance, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>(), false, AssembliesToScan);
}
protected virtual IEnumerable<Assembly> AssembliesToScan

View File

@@ -40,7 +40,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Composing
[Test]
public void Find_Class_Of_Type_With_Attribute()
{
var typeFinder = new TypeFinder(Mock.Of<ILogger<TypeFinder>>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance), new VaryingRuntimeHash());
var typeFinder = new TypeFinder(Mock.Of<ILogger<TypeFinder>>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance));
IEnumerable<Type> typesFound = typeFinder.FindClassesOfTypeWithAttribute<TestEditor, MyTestAttribute>(_assemblies);
Assert.AreEqual(2, typesFound.Count());
}
@@ -48,7 +48,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Composing
[Test]
public void Find_Classes_With_Attribute()
{
var typeFinder = new TypeFinder(Mock.Of<ILogger<TypeFinder>>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance), new VaryingRuntimeHash());
var typeFinder = new TypeFinder(Mock.Of<ILogger<TypeFinder>>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance));
IEnumerable<Type> typesFound = typeFinder.FindClassesWithAttribute<TreeAttribute>(_assemblies);
Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree]

View File

@@ -48,6 +48,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Composing
};
_typeLoader = new TypeLoader(
typeFinder,
new VaryingRuntimeHash(),
NoAppCache.Instance,
new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)),
Mock.Of<ILogger<TypeLoader>>(),

View File

@@ -106,7 +106,14 @@ namespace Umbraco.Extensions
IProfiler profiler = GetWebProfiler(config);
ILoggerFactory loggerFactory = LoggerFactory.Create(cfg => cfg.AddSerilog(Log.Logger, false));
TypeLoader typeLoader = services.AddTypeLoader(Assembly.GetEntryAssembly(), tempHostingEnvironment, loggerFactory, appCaches, config, profiler);
TypeLoader typeLoader = services.AddTypeLoader(
Assembly.GetEntryAssembly(),
tempHostingEnvironment,
loggerFactory,
appCaches,
config,
profiler);
// adds the umbraco startup filter which will call UseUmbraco early on before
// other start filters are applied (depending on the ordering of IStartupFilters in DI).

View File

@@ -3,6 +3,7 @@ using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
@@ -60,37 +61,22 @@ namespace Umbraco.Extensions
return services;
}
internal static ITypeFinder AddTypeFinder(
this IServiceCollection services,
ILoggerFactory loggerFactory,
Assembly entryAssembly,
IConfiguration config,
IProfiler profiler)
{
TypeFinderSettings typeFinderSettings = config.GetSection(Cms.Core.Constants.Configuration.ConfigTypeFinder).Get<TypeFinderSettings>() ?? new TypeFinderSettings();
var assemblyProvider = new DefaultUmbracoAssemblyProvider(entryAssembly, loggerFactory);
RuntimeHashPaths runtimeHashPaths = new RuntimeHashPaths().AddAssemblies(assemblyProvider);
var runtimeHash = new RuntimeHash(
new ProfilingLogger(
loggerFactory.CreateLogger<RuntimeHash>(),
profiler),
runtimeHashPaths);
var typeFinder = new TypeFinder(
loggerFactory.CreateLogger<TypeFinder>(),
assemblyProvider,
runtimeHash,
new TypeFinderConfig(Options.Create(typeFinderSettings))
);
services.AddUnique<ITypeFinder>(typeFinder);
return typeFinder;
}
/// <summary>
/// Called to create the <see cref="TypeLoader"/> to assign to the <see cref="IUmbracoBuilder"/>
/// </summary>
/// <param name="services"></param>
/// <param name="entryAssembly"></param>
/// <param name="hostingEnvironment"></param>
/// <param name="loggerFactory"></param>
/// <param name="appCaches"></param>
/// <param name="configuration"></param>
/// <param name="profiler"></param>
/// <returns></returns>
/// <remarks>
/// This should never be called in a web project. It is used internally by Umbraco but could be used in unit tests.
/// If called in a web project it will have no affect except to create and return a new TypeLoader but this will not
/// be the instance in DI.
/// </remarks>
public static TypeLoader AddTypeLoader(
this IServiceCollection services,
Assembly entryAssembly,
@@ -100,17 +86,42 @@ namespace Umbraco.Extensions
IConfiguration configuration,
IProfiler profiler)
{
ITypeFinder typeFinder = services.AddTypeFinder(loggerFactory, entryAssembly, configuration, profiler);
TypeFinderSettings typeFinderSettings = configuration.GetSection(Cms.Core.Constants.Configuration.ConfigTypeFinder).Get<TypeFinderSettings>() ?? new TypeFinderSettings();
var assemblyProvider = new DefaultUmbracoAssemblyProvider(
entryAssembly,
loggerFactory,
typeFinderSettings.AdditionalEntryAssemblies);
RuntimeHashPaths runtimeHashPaths = new RuntimeHashPaths().AddAssemblies(assemblyProvider);
var runtimeHash = new RuntimeHash(
new ProfilingLogger(
loggerFactory.CreateLogger<RuntimeHash>(),
profiler),
runtimeHashPaths);
var typeFinderConfig = new TypeFinderConfig(Options.Create(typeFinderSettings));
var typeFinder = new TypeFinder(
loggerFactory.CreateLogger<TypeFinder>(),
assemblyProvider,
typeFinderConfig
);
var typeLoader = new TypeLoader(
typeFinder,
runtimeHash,
appCaches.RuntimeCache,
new DirectoryInfo(hostingEnvironment.LocalTempPath),
loggerFactory.CreateLogger<TypeLoader>(),
profiler
);
services.AddUnique<TypeLoader>(typeLoader);
// This will add it ONCE and not again which is what we want since we don't actually want people to call this method
// in the web project.
services.TryAddSingleton<ITypeFinder>(typeFinder);
services.TryAddSingleton<TypeLoader>(typeLoader);
return typeLoader;
}