diff --git a/src/Umbraco.Abstractions/Cache/FastDictionaryAppCache.cs b/src/Umbraco.Abstractions/Cache/FastDictionaryAppCache.cs index 35ba4d08ca..159f9cd7cb 100644 --- a/src/Umbraco.Abstractions/Cache/FastDictionaryAppCache.cs +++ b/src/Umbraco.Abstractions/Cache/FastDictionaryAppCache.cs @@ -12,6 +12,13 @@ namespace Umbraco.Core.Cache /// public class FastDictionaryAppCache : IAppCache { + private readonly ITypeFinder _typeFinder; + + public FastDictionaryAppCache(ITypeFinder typeFinder) + { + _typeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder)); + } + /// /// Gets the internal items dictionary, for tests only! /// @@ -78,7 +85,7 @@ namespace Umbraco.Core.Cache /// public void ClearOfType(string typeName) { - var type = TypeHelper.GetTypeByName(typeName); + var type = _typeFinder.GetTypeByName(typeName); if (type == null) return; var isInterface = type.IsInterface; diff --git a/src/Umbraco.Abstractions/Cache/FastDictionaryAppCacheBase.cs b/src/Umbraco.Abstractions/Cache/FastDictionaryAppCacheBase.cs index b49ecea671..57f4e7b9a2 100644 --- a/src/Umbraco.Abstractions/Cache/FastDictionaryAppCacheBase.cs +++ b/src/Umbraco.Abstractions/Cache/FastDictionaryAppCacheBase.cs @@ -12,6 +12,13 @@ namespace Umbraco.Core.Cache /// public abstract class FastDictionaryAppCacheBase : IAppCache { + private readonly ITypeFinder _typeFinder; + + protected FastDictionaryAppCacheBase(ITypeFinder typeFinder) + { + _typeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder)); + } + // prefix cache keys so we know which one are ours protected const string CacheItemPrefix = "umbrtmche"; @@ -116,7 +123,7 @@ namespace Umbraco.Core.Cache /// public virtual void ClearOfType(string typeName) { - var type = TypeHelper.GetTypeByName(typeName); + var type = _typeFinder.GetTypeByName(typeName); if (type == null) return; var isInterface = type.IsInterface; try diff --git a/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs b/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs index 4fad382cc8..41c930ae86 100644 --- a/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs +++ b/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web; +using Umbraco.Core.Composing; namespace Umbraco.Core.Cache { @@ -20,7 +21,7 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance of the class with a context, for unit tests! /// - public HttpRequestAppCache(Func requestItems) + public HttpRequestAppCache(Func requestItems, ITypeFinder typeFinder) : base(typeFinder) { ContextItems = requestItems; } diff --git a/src/Umbraco.Abstractions/Cache/ObjectCacheAppCache.cs b/src/Umbraco.Abstractions/Cache/ObjectCacheAppCache.cs index 7d5081baa5..208390276a 100644 --- a/src/Umbraco.Abstractions/Cache/ObjectCacheAppCache.cs +++ b/src/Umbraco.Abstractions/Cache/ObjectCacheAppCache.cs @@ -13,13 +13,15 @@ namespace Umbraco.Core.Cache /// public class ObjectCacheAppCache : IAppPolicyCache { + private readonly ITypeFinder _typeFinder; private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); /// /// Initializes a new instance of the . /// - public ObjectCacheAppCache() + public ObjectCacheAppCache(ITypeFinder typeFinder) { + _typeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder)); // the MemoryCache is created with name "in-memory". That name is // used to retrieve configuration options. It does not identify the memory cache, i.e. // each instance of this class has its own, independent, memory cache. @@ -178,7 +180,7 @@ namespace Umbraco.Core.Cache /// public virtual void ClearOfType(string typeName) { - var type = TypeHelper.GetTypeByName(typeName); + var type = _typeFinder.GetTypeByName(typeName); if (type == null) return; var isInterface = type.IsInterface; try diff --git a/src/Umbraco.Core/Composing/ITypeFinder.cs b/src/Umbraco.Abstractions/Composing/ITypeFinder.cs similarity index 97% rename from src/Umbraco.Core/Composing/ITypeFinder.cs rename to src/Umbraco.Abstractions/Composing/ITypeFinder.cs index 844719b782..d5908f9c54 100644 --- a/src/Umbraco.Core/Composing/ITypeFinder.cs +++ b/src/Umbraco.Abstractions/Composing/ITypeFinder.cs @@ -6,6 +6,8 @@ namespace Umbraco.Core.Composing { public interface ITypeFinder { + Type GetTypeByName(string name); + /// /// Return a list of found local Assemblies that Umbraco should scan for type finding /// diff --git a/src/Umbraco.Core/Composing/TypeFinderExtensions.cs b/src/Umbraco.Abstractions/Composing/TypeFinderExtensions.cs similarity index 100% rename from src/Umbraco.Core/Composing/TypeFinderExtensions.cs rename to src/Umbraco.Abstractions/Composing/TypeFinderExtensions.cs diff --git a/src/Umbraco.Abstractions/Composing/TypeHelper.cs b/src/Umbraco.Abstractions/Composing/TypeHelper.cs index 1752521b5d..28eab6a5ec 100644 --- a/src/Umbraco.Abstractions/Composing/TypeHelper.cs +++ b/src/Umbraco.Abstractions/Composing/TypeHelper.cs @@ -19,28 +19,10 @@ namespace Umbraco.Core.Composing = new ConcurrentDictionary, PropertyInfo[]>(); private static readonly ConcurrentDictionary GetFieldsCache = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary TypeNamesCache - = new ConcurrentDictionary(); - + private static readonly Assembly[] EmptyAssemblies = new Assembly[0]; - /// - /// Returns a Type for the string type name - /// - /// - /// - public static Type GetTypeByName(string name) - { - // First try using the basic functionality - var type = Type.GetType(name); - if (type != null) return type; - - // It didn't parse, so try loading from each already loaded assembly and cache it - return TypeNamesCache.GetOrAdd(name, s => - AppDomain.CurrentDomain.GetAssemblies() - .Select(x => x.GetType(s)) - .FirstOrDefault(x => x != null)); - } + /// /// Based on a type we'll check if it is IEnumerable{T} (or similar) and if so we'll return a List{T}, this will also deal with array types and return List{T} for those too. diff --git a/src/Umbraco.Core/Composing/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs index a1b1bf2fef..03fe115bbc 100644 --- a/src/Umbraco.Core/Composing/TypeFinder.cs +++ b/src/Umbraco.Core/Composing/TypeFinder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Configuration; using System.IO; @@ -115,6 +116,7 @@ namespace Umbraco.Core.Composing private readonly object _localFilteredAssemblyCacheLocker = new object(); private readonly List _notifiedLoadExceptionAssemblies = new List(); private string[] _assembliesAcceptingLoadExceptions; + private static readonly ConcurrentDictionary TypeNamesCache= new ConcurrentDictionary(); private string[] AssembliesAcceptingLoadExceptions { @@ -310,8 +312,47 @@ namespace Umbraco.Core.Composing return GetClassesWithAttribute(attributeType, assemblyList, onlyConcreteClasses); } + /// + /// Returns a Type for the string type name + /// + /// + /// + public virtual Type GetTypeByName(string name) + { + // This is exactly what the BuildManager does, if the type is an assembly qualified type + // name it will find it. + if (TypeNameContainsAssembly(name)) + { + return Type.GetType(name); + } + + // It didn't parse, so try loading from each already loaded assembly and cache it + return TypeNamesCache.GetOrAdd(name, s => + AppDomain.CurrentDomain.GetAssemblies() + .Select(x => x.GetType(s)) + .FirstOrDefault(x => x != null)); + } + #region Private methods + // borrowed from aspnet System.Web.UI.Util + private static bool TypeNameContainsAssembly(string typeName) + { + return CommaIndexInTypeName(typeName) > 0; + } + + // borrowed from aspnet System.Web.UI.Util + private static int CommaIndexInTypeName(string typeName) + { + var num1 = typeName.LastIndexOf(','); + if (num1 < 0) + return -1; + var num2 = typeName.LastIndexOf(']'); + if (num2 > num1) + return -1; + return typeName.IndexOf(',', num2 + 1); + } + private IEnumerable GetClassesWithAttribute( Type attributeType, IEnumerable assemblies, @@ -510,5 +551,6 @@ namespace Umbraco.Core.Composing #endregion + } } diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index daa95ede49..1ee302aa6c 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -5,11 +5,9 @@ using System.Linq; using System.Reflection; using System.Text; using System.Threading; -using System.Web; using System.Web.Compilation; using Umbraco.Core.Cache; using Umbraco.Core.Collections; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; using File = System.IO.File; @@ -729,18 +727,13 @@ namespace Umbraco.Core.Composing // successfully retrieved types from the file cache: load foreach (var type in cacheResult.Result) { - try - { - // we use the build manager to ensure we get all types loaded, this is slightly slower than - // Type.GetType but if the types in the assembly aren't loaded yet it would fail whereas - // BuildManager will load them - this is how eg MVC loads types, etc - no need to make it - // more complicated - typeList.Add(BuildManager.GetType(type, true)); - } - catch (Exception ex) + var resolvedType = TypeFinder.GetTypeByName(type); + if (resolvedType != null) + typeList.Add(resolvedType); + else { // in case of any exception, we have to exit, and revert to scanning - _logger.Error(ex, "Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type); + _logger.Warn("Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type); scan = true; break; } diff --git a/src/Umbraco.Core/CompositionExtensions_Essentials.cs b/src/Umbraco.Core/CompositionExtensions_Essentials.cs index b85479716c..e4be927f71 100644 --- a/src/Umbraco.Core/CompositionExtensions_Essentials.cs +++ b/src/Umbraco.Core/CompositionExtensions_Essentials.cs @@ -19,7 +19,8 @@ namespace Umbraco.Core AppCaches appCaches, IUmbracoDatabaseFactory databaseFactory, TypeLoader typeLoader, - IRuntimeState state) + IRuntimeState state, + ITypeFinder typeFinder) { composition.RegisterUnique(logger); composition.RegisterUnique(profiler); @@ -30,6 +31,7 @@ namespace Umbraco.Core composition.RegisterUnique(factory => factory.GetInstance().SqlContext); composition.RegisterUnique(typeLoader); composition.RegisterUnique(state); + composition.RegisterUnique(typeFinder); } } } diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 8ccb740cc2..192d449d12 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -42,6 +42,11 @@ namespace Umbraco.Core.Runtime /// protected IProfilingLogger ProfilingLogger { get; private set; } + /// + /// Gets the + /// + protected ITypeFinder TypeFinder { get; private set; } + /// public IRuntimeState State => _state; @@ -56,6 +61,9 @@ namespace Umbraco.Core.Runtime var profiler = Profiler = GetProfiler(); var profilingLogger = ProfilingLogger = new ProfilingLogger(logger, profiler); + // type finder + TypeFinder = GetTypeFinder(); + // the boot loader boots using a container scope, so anything that is PerScope will // be disposed after the boot loader has booted, and anything else will remain. // note that this REQUIRES that perWebRequestScope has NOT been enabled yet, else @@ -112,8 +120,7 @@ namespace Umbraco.Core.Runtime var configs = GetConfigs(); // type finder/loader - var typeFinder = new TypeFinder(Logger); - var typeLoader = new TypeLoader(typeFinder, appCaches.RuntimeCache, configs.Global().LocalTempPath, ProfilingLogger); + var typeLoader = new TypeLoader(TypeFinder, appCaches.RuntimeCache, configs.Global().LocalTempPath, ProfilingLogger); // runtime state // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' @@ -131,7 +138,7 @@ namespace Umbraco.Core.Runtime // create the composition composition = new Composition(register, typeLoader, ProfilingLogger, _state, configs); - composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, mainDom, appCaches, databaseFactory, typeLoader, _state); + composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, mainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder); // run handlers RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); @@ -289,7 +296,6 @@ namespace Umbraco.Core.Runtime /// public virtual void Compose(Composition composition) { - // nothing } #region Getters @@ -314,6 +320,13 @@ namespace Umbraco.Core.Runtime protected virtual IProfiler GetProfiler() => new LogProfiler(Logger); + /// + /// Gets a + /// + /// + protected virtual ITypeFinder GetTypeFinder() + => new TypeFinder(Logger); + /// /// Gets the application caches. /// @@ -324,9 +337,9 @@ namespace Umbraco.Core.Runtime // is overridden by the web runtime return new AppCaches( - new DeepCloneAppCache(new ObjectCacheAppCache()), + new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder)), NoAppCache.Instance, - new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); + new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder)))); } // by default, returns null, meaning that Umbraco should auto-detect the application root path. diff --git a/src/Umbraco.Core/Scoping/Scope.cs b/src/Umbraco.Core/Scoping/Scope.cs index 84273e23da..3eabfbca9b 100644 --- a/src/Umbraco.Core/Scoping/Scope.cs +++ b/src/Umbraco.Core/Scoping/Scope.cs @@ -17,6 +17,7 @@ namespace Umbraco.Core.Scoping { private readonly ScopeProvider _scopeProvider; private readonly ILogger _logger; + private readonly ITypeFinder _typeFinder; private readonly IsolationLevel _isolationLevel; private readonly RepositoryCacheMode _repositoryCacheMode; @@ -35,7 +36,7 @@ namespace Umbraco.Core.Scoping // initializes a new scope private Scope(ScopeProvider scopeProvider, - ILogger logger, FileSystems fileSystems, Scope parent, ScopeContext scopeContext, bool detachable, + ILogger logger, ITypeFinder typeFinder, FileSystems fileSystems, Scope parent, ScopeContext scopeContext, bool detachable, IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, @@ -45,6 +46,7 @@ namespace Umbraco.Core.Scoping { _scopeProvider = scopeProvider; _logger = logger; + _typeFinder = typeFinder; Context = scopeContext; @@ -109,26 +111,26 @@ namespace Umbraco.Core.Scoping // initializes a new scope public Scope(ScopeProvider scopeProvider, - ILogger logger, FileSystems fileSystems, bool detachable, ScopeContext scopeContext, + ILogger logger, ITypeFinder typeFinder, FileSystems fileSystems, bool detachable, ScopeContext scopeContext, IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null, bool callContext = false, bool autoComplete = false) - : this(scopeProvider, logger, fileSystems, null, scopeContext, detachable, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete) + : this(scopeProvider, logger, typeFinder, fileSystems, null, scopeContext, detachable, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete) { } // initializes a new scope in a nested scopes chain, with its parent public Scope(ScopeProvider scopeProvider, - ILogger logger, FileSystems fileSystems, Scope parent, + ILogger logger, ITypeFinder typeFinder, FileSystems fileSystems, Scope parent, IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null, bool callContext = false, bool autoComplete = false) - : this(scopeProvider, logger, fileSystems, parent, null, false, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete) + : this(scopeProvider, logger, typeFinder, fileSystems, parent, null, false, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete) { } public Guid InstanceId { get; } = Guid.NewGuid(); @@ -175,7 +177,7 @@ namespace Umbraco.Core.Scoping if (ParentScope != null) return ParentScope.IsolatedCaches; return _isolatedCaches ?? (_isolatedCaches - = new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); + = new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache(_typeFinder)))); } } diff --git a/src/Umbraco.Core/Scoping/ScopeProvider.cs b/src/Umbraco.Core/Scoping/ScopeProvider.cs index 3c0fa94327..60cb83fcd5 100644 --- a/src/Umbraco.Core/Scoping/ScopeProvider.cs +++ b/src/Umbraco.Core/Scoping/ScopeProvider.cs @@ -22,13 +22,15 @@ namespace Umbraco.Core.Scoping internal class ScopeProvider : IScopeProvider, IScopeAccessor { private readonly ILogger _logger; + private readonly ITypeFinder _typeFinder; private readonly FileSystems _fileSystems; - public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, ILogger logger) + public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, ILogger logger, ITypeFinder typeFinder) { DatabaseFactory = databaseFactory; _fileSystems = fileSystems; _logger = logger; + _typeFinder = typeFinder; // take control of the FileSystems _fileSystems.IsScoped = () => AmbientScope != null && AmbientScope.ScopedFileSystems; @@ -323,7 +325,7 @@ namespace Umbraco.Core.Scoping IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null) { - return new Scope(this, _logger, _fileSystems, true, null, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems); + return new Scope(this, _logger, _typeFinder, _fileSystems, true, null, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems); } /// @@ -379,13 +381,13 @@ namespace Umbraco.Core.Scoping { var ambientContext = AmbientContext; var newContext = ambientContext == null ? new ScopeContext() : null; - var scope = new Scope(this, _logger, _fileSystems, false, newContext, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete); + var scope = new Scope(this, _logger, _typeFinder, _fileSystems, false, newContext, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete); // assign only if scope creation did not throw! SetAmbient(scope, newContext ?? ambientContext); return scope; } - var nested = new Scope(this, _logger, _fileSystems, ambientScope, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete); + var nested = new Scope(this, _logger, _typeFinder, _fileSystems, ambientScope, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete); SetAmbient(nested, AmbientContext); return nested; } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index bfffc037ce..6643164020 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -136,9 +136,7 @@ - - diff --git a/src/Umbraco.Examine/LuceneIndexCreator.cs b/src/Umbraco.Examine/LuceneIndexCreator.cs index 97a929c9c8..47c4cce143 100644 --- a/src/Umbraco.Examine/LuceneIndexCreator.cs +++ b/src/Umbraco.Examine/LuceneIndexCreator.cs @@ -17,6 +17,13 @@ namespace Umbraco.Examine /// public abstract class LuceneIndexCreator : IIndexCreator { + private readonly ITypeFinder _typeFinder; + + protected LuceneIndexCreator(ITypeFinder typeFinder) + { + _typeFinder = typeFinder; + } + public abstract IEnumerable Create(); /// @@ -38,7 +45,7 @@ namespace Umbraco.Examine if (!configuredDirectoryFactory.IsNullOrWhiteSpace()) { //this should be a fully qualified type - var factoryType = TypeHelper.GetTypeByName(configuredDirectoryFactory); + var factoryType = _typeFinder.GetTypeByName(configuredDirectoryFactory); if (factoryType == null) throw new NullReferenceException("No directory type found for value: " + configuredDirectoryFactory); var directoryFactory = (IDirectoryFactory)Activator.CreateInstance(factoryType); return directoryFactory.CreateDirectory(dirInfo); diff --git a/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs b/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs index c17d29a88f..77200be86e 100644 --- a/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs @@ -2,10 +2,13 @@ using System.Diagnostics; using System.Reflection; using System.Web; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Collections; +using Umbraco.Core.Composing; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Tests.Collections; @@ -23,7 +26,8 @@ namespace Umbraco.Tests.Cache public override void Setup() { base.Setup(); - _provider = new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache)); + var typeFinder = new TypeFinder(Mock.Of()); + _provider = new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache, typeFinder)); } internal override IAppCache AppCache => _provider; diff --git a/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs index 81a784fc01..b9c948c1de 100644 --- a/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs +++ b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs @@ -1,5 +1,8 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; +using Umbraco.Core.Logging; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Cache @@ -13,8 +16,9 @@ namespace Umbraco.Tests.Cache public override void Setup() { base.Setup(); + var typeFinder = new TypeFinder(Mock.Of()); _ctx = new FakeHttpContextFactory("http://localhost/test"); - _appCache = new HttpRequestAppCache(() => _ctx.HttpContext.Items); + _appCache = new HttpRequestAppCache(() => _ctx.HttpContext.Items, typeFinder); } internal override IAppCache AppCache diff --git a/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs b/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs index b9c729f891..0fb8e574a8 100644 --- a/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs +++ b/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs @@ -1,9 +1,12 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; +using Umbraco.Core.Logging; namespace Umbraco.Tests.Cache { @@ -20,7 +23,8 @@ namespace Umbraco.Tests.Cache public override void Setup() { base.Setup(); - _provider = new ObjectCacheAppCache(); + var typeFinder = new TypeFinder(Mock.Of()); + _provider = new ObjectCacheAppCache(typeFinder); } internal override IAppCache AppCache diff --git a/src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs b/src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs index 84a946036a..02986e2f78 100644 --- a/src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs +++ b/src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs @@ -1,8 +1,11 @@ using System; using System.Diagnostics; using System.Web; +using Moq; using NUnit.Framework; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; +using Umbraco.Core.Logging; using Umbraco.Web.Cache; namespace Umbraco.Tests.Cache @@ -17,7 +20,8 @@ namespace Umbraco.Tests.Cache public override void Setup() { base.Setup(); - _appCache = new WebCachingAppCache(HttpRuntime.Cache); + var typeFinder = new TypeFinder(Mock.Of()); + _appCache = new WebCachingAppCache(HttpRuntime.Cache, typeFinder); } internal override IAppCache AppCache => _appCache; diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 2bd0d5d471..4fa25c2121 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -31,9 +31,10 @@ namespace Umbraco.Tests.Components var mock = new Mock(); var logger = Mock.Of(); + var typeFinder = new TypeFinder(logger); var f = new UmbracoDatabaseFactory(logger, new Lazy(() => new MapperCollection(Enumerable.Empty()))); var fs = new FileSystems(mock.Object, logger); - var p = new ScopeProvider(f, fs, logger); + var p = new ScopeProvider(f, fs, logger, typeFinder); mock.Setup(x => x.GetInstance(typeof (ILogger))).Returns(logger); mock.Setup(x => x.GetInstance(typeof (IProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of())); diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index 9cc1d14954..0c57c70742 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -1,7 +1,9 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Macros; @@ -15,11 +17,12 @@ namespace Umbraco.Tests.Macros [SetUp] public void Setup() { + var typeFinder = new TypeFinder(Mock.Of()); //we DO want cache enabled for these tests var cacheHelper = new AppCaches( - new ObjectCacheAppCache(), + new ObjectCacheAppCache(typeFinder), NoAppCache.Instance, - new IsolatedCaches(type => new ObjectCacheAppCache())); + new IsolatedCaches(type => new ObjectCacheAppCache(typeFinder))); //Current.ApplicationContext = new ApplicationContext(cacheHelper, new ProfilingLogger(Mock.Of(), Mock.Of())); Current.Reset(); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 524d6fe5b1..ffbf462b8e 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json; using Umbraco.Core; using NUnit.Framework; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Composing.CompositionExtensions; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; @@ -269,7 +270,7 @@ namespace Umbraco.Tests.Models content.UpdateDate = DateTime.Now; content.WriterId = 23; - var runtimeCache = new ObjectCacheAppCache(); + var runtimeCache = new ObjectCacheAppCache(new TypeFinder(Mock.Of())); runtimeCache.Insert(content.Id.ToString(CultureInfo.InvariantCulture), () => content); var proflog = GetTestProfilingLogger(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 4d62ec8301..af27d47f97 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -77,9 +77,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void CacheActiveForIntsAndGuids() { var realCache = new AppCaches( - new ObjectCacheAppCache(), + new ObjectCacheAppCache(TypeFinder), new DictionaryAppCache(), - new IsolatedCaches(t => new ObjectCacheAppCache())); + new IsolatedCaches(t => new ObjectCacheAppCache(TypeFinder))); var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index d04382e32e..fa916b554d 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -49,9 +49,9 @@ namespace Umbraco.Tests.Persistence.Repositories MediaTypeRepository mediaTypeRepository; var realCache = new AppCaches( - new ObjectCacheAppCache(), + new ObjectCacheAppCache(TypeFinder), new DictionaryAppCache(), - new IsolatedCaches(t => new ObjectCacheAppCache())); + new IsolatedCaches(t => new ObjectCacheAppCache(TypeFinder))); var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) diff --git a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs index 2f009d147e..fe2b080310 100644 --- a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs +++ b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs @@ -4,6 +4,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; @@ -124,8 +125,9 @@ namespace Umbraco.Tests.Published var setType1 = publishedContentTypeFactory.CreateContentType(1000, "set1", CreatePropertyTypes); - var elementsCache = new FastDictionaryAppCache(); - var snapshotCache = new FastDictionaryAppCache(); + var typeFinder = new TypeFinder(Mock.Of()); + var elementsCache = new FastDictionaryAppCache(typeFinder); + var snapshotCache = new FastDictionaryAppCache(typeFinder); var publishedSnapshot = new Mock(); publishedSnapshot.Setup(x => x.SnapshotCache).Returns(snapshotCache); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs index 5d32606ee7..564e129650 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs @@ -138,6 +138,8 @@ namespace Umbraco.Tests.PublishedContent // create a data source for NuCache _source = new TestDataSource(kits); + var typeFinder = new TypeFinder(Mock.Of()); + // at last, create the complete NuCache snapshot service! var options = new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }; _snapshotService = new PublishedSnapshotService(options, @@ -158,7 +160,8 @@ namespace Umbraco.Tests.PublishedContent globalSettings, Mock.Of(), Mock.Of(), - new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() })); + new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }), + typeFinder); // invariant is the current default _variationAccesor.VariationContext = new VariationContext(); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index 0e05e6baad..d3a4a0d082 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -181,6 +181,8 @@ namespace Umbraco.Tests.PublishedContent // create a variation accessor _variationAccesor = new TestVariationContextAccessor(); + var typeFinder = new TypeFinder(Mock.Of()); + // at last, create the complete NuCache snapshot service! var options = new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }; _snapshotService = new PublishedSnapshotService(options, @@ -201,7 +203,8 @@ namespace Umbraco.Tests.PublishedContent globalSettings, Mock.Of(), Mock.Of(), - new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() })); + new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }), + typeFinder); // invariant is the current default _variationAccesor.VariationContext = new VariationContext(); diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index a205478246..d1f2f48ed7 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Runtimes // create the register and the composition var register = RegisterFactory.Create(); var composition = new Composition(register, typeLoader, profilingLogger, runtimeState); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder); // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(); @@ -260,7 +260,7 @@ namespace Umbraco.Tests.Runtimes // create the register and the composition var register = RegisterFactory.Create(); var composition = new Composition(register, typeLoader, profilingLogger, runtimeState); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder); // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index c7c403b260..0d2243c6dc 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -82,6 +82,8 @@ namespace Umbraco.Tests.Scoping var mediaRepository = Mock.Of(); var memberRepository = Mock.Of(); + var typeFinder = new TypeFinder(Mock.Of()); + return new PublishedSnapshotService( options, null, @@ -99,7 +101,8 @@ namespace Umbraco.Tests.Scoping Factory.GetInstance(), Factory.GetInstance(), Mock.Of(), - new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() })); + new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }), + typeFinder); } protected UmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null) diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index c7e4ddcb19..ae4544bf87 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -43,9 +43,9 @@ namespace Umbraco.Tests.Scoping { // this is what's created core web runtime return new AppCaches( - new DeepCloneAppCache(new ObjectCacheAppCache()), + new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder)), NoAppCache.Instance, - new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); + new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder)))); } [TearDown] diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index 0fe05f385f..bc515cfea3 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; @@ -53,6 +54,8 @@ namespace Umbraco.Tests.Services var mediaRepository = Mock.Of(); var memberRepository = Mock.Of(); + var typeFinder = new TypeFinder(Mock.Of()); + return new PublishedSnapshotService( options, null, @@ -70,7 +73,8 @@ namespace Umbraco.Tests.Services Factory.GetInstance(), Factory.GetInstance(), Mock.Of(), - new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() })); + new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }), + typeFinder); } public class LocalServerMessenger : ServerMessengerBase diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 56ad22d414..4464a98511 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -230,7 +230,7 @@ namespace Umbraco.Tests.TestHelpers return container?.TryGetInstance() ?? Mock.Of(); } - public IScopeProvider GetScopeProvider(ILogger logger, FileSystems fileSystems = null, IUmbracoDatabaseFactory databaseFactory = null) + public IScopeProvider GetScopeProvider(ILogger logger, ITypeFinder typeFinder = null, FileSystems fileSystems = null, IUmbracoDatabaseFactory databaseFactory = null) { if (databaseFactory == null) { @@ -241,8 +241,9 @@ namespace Umbraco.Tests.TestHelpers databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, logger, new Lazy(() => mappers)); } + typeFinder = typeFinder ?? new TypeFinder(logger); fileSystems = fileSystems ?? new FileSystems(Current.Factory, logger); - var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, logger); + var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, logger, typeFinder); return scopeProvider; } } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 4a911680ab..38147fe45d 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -99,6 +99,8 @@ namespace Umbraco.Tests.Testing protected ILogger Logger => Factory.GetInstance(); + protected ITypeFinder TypeFinder => Factory.GetInstance(); + protected IProfiler Profiler => Factory.GetInstance(); protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance(); @@ -137,6 +139,7 @@ namespace Umbraco.Tests.Testing Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run)); + Composition.RegisterUnique(typeLoader.TypeFinder); Composition.RegisterUnique(typeLoader); Composition.RegisterUnique(logger); Composition.RegisterUnique(profiler); @@ -358,7 +361,7 @@ namespace Umbraco.Tests.Testing Composition.WithCollectionBuilder(); // empty Composition.RegisterUnique(factory - => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); + => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); Composition.RegisterUnique(factory => (IScopeAccessor) factory.GetInstance()); Composition.ComposeServices(); diff --git a/src/Umbraco.Web/Cache/WebCachingAppCache.cs b/src/Umbraco.Web/Cache/WebCachingAppCache.cs index 3d169699f0..1879e8b69b 100644 --- a/src/Umbraco.Web/Cache/WebCachingAppCache.cs +++ b/src/Umbraco.Web/Cache/WebCachingAppCache.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Web.Caching; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; namespace Umbraco.Web.Cache { @@ -25,7 +26,7 @@ namespace Umbraco.Web.Cache /// /// Initializes a new instance of the class. /// - public WebCachingAppCache(System.Web.Caching.Cache cache) + public WebCachingAppCache(System.Web.Caching.Cache cache, ITypeFinder typeFinder) : base(typeFinder) { _cache = cache; } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index eae2f33979..554e76c665 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -8,6 +8,7 @@ using CSharpTest.Net.Collections; using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -46,6 +47,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IPublishedModelFactory _publishedModelFactory; private readonly IDefaultCultureAccessor _defaultCultureAccessor; private readonly UrlSegmentProviderCollection _urlSegmentProviders; + private readonly ITypeFinder _typeFinder; // volatile because we read it with no lock private volatile bool _isReady; @@ -77,7 +79,8 @@ namespace Umbraco.Web.PublishedCache.NuCache IDataSource dataSource, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer, IPublishedModelFactory publishedModelFactory, - UrlSegmentProviderCollection urlSegmentProviders) + UrlSegmentProviderCollection urlSegmentProviders, + ITypeFinder typeFinder) : base(publishedSnapshotAccessor, variationContextAccessor) { //if (Interlocked.Increment(ref _singletonCheck) > 1) @@ -94,6 +97,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _defaultCultureAccessor = defaultCultureAccessor; _globalSettings = globalSettings; _urlSegmentProviders = urlSegmentProviders; + _typeFinder = typeFinder; // we need an Xml serializer here so that the member cache can support XPath, // for members this is done by navigating the serialized-to-xml member @@ -1162,7 +1166,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _contentGen = contentSnap.Gen; _mediaGen = mediaSnap.Gen; _domainGen = domainSnap.Gen; - elementsCache = _elementsCache = new FastDictionaryAppCache(); + elementsCache = _elementsCache = new FastDictionaryAppCache(_typeFinder); } } diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 09446e1dab..49db6646de 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -62,13 +62,13 @@ namespace Umbraco.Web.Runtime protected override AppCaches GetAppCaches() => new AppCaches( // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache)), + new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache, TypeFinder)), // we need request based cache when running in web-based context - new HttpRequestAppCache(() => HttpContext.Current?.Items), + new HttpRequestAppCache(() => HttpContext.Current?.Items, TypeFinder), new IsolatedCaches(type => // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneAppCache(new ObjectCacheAppCache()))); + new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder)))); #endregion } diff --git a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs index ec536b9d75..b9dbc7d996 100644 --- a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs +++ b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs @@ -7,6 +7,7 @@ using Lucene.Net.Analysis.Standard; using Examine.LuceneEngine; using Examine; using Umbraco.Core; +using Umbraco.Core.Composing; namespace Umbraco.Web.Search { @@ -17,10 +18,12 @@ namespace Umbraco.Web.Search { // TODO: we should inject the different IValueSetValidator so devs can just register them instead of overriding this class? - public UmbracoIndexesCreator(IProfilingLogger profilingLogger, + public UmbracoIndexesCreator( + ITypeFinder typeFinder, + IProfilingLogger profilingLogger, ILocalizationService languageService, IPublicAccessService publicAccessService, - IMemberService memberService, IUmbracoIndexConfig umbracoIndexConfig) + IMemberService memberService, IUmbracoIndexConfig umbracoIndexConfig) : base(typeFinder) { ProfilingLogger = profilingLogger ?? throw new System.ArgumentNullException(nameof(profilingLogger)); LanguageService = languageService ?? throw new System.ArgumentNullException(nameof(languageService));