diff --git a/src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs b/src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs
new file mode 100644
index 0000000000..04d0d70475
--- /dev/null
+++ b/src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Security;
+using Umbraco.Core.Exceptions;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// lazily load a reference to all local assemblies and gac assemblies
+ ///
+ ///
+ /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
+ ///
+ /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
+ /// loaded in the CLR, not all assemblies.
+ /// See these threads:
+ /// http://issues.umbraco.org/issue/U5-198
+ /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app
+ /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl
+ ///
+ public class BruteForceAssemblyProvider : IAssemblyProvider
+ {
+ public BruteForceAssemblyProvider()
+ {
+ _allAssemblies = new Lazy>(() =>
+ {
+ HashSet assemblies = null;
+ try
+ {
+ //NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have
+ // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one.
+ var binFolder = GetRootDirectorySafe();
+ var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
+ assemblies = new HashSet();
+ foreach (var a in binAssemblyFiles)
+ {
+ try
+ {
+ var assName = AssemblyName.GetAssemblyName(a);
+ var ass = Assembly.Load(assName);
+ assemblies.Add(ass);
+ }
+ catch (Exception e)
+ {
+ if (e is SecurityException || e is BadImageFormatException)
+ {
+ //swallow these exceptions
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ //Since we are only loading in the /bin assemblies above, we will also load in anything that's already loaded (which will include gac items)
+ foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ assemblies.Add(a);
+ }
+ }
+ catch (InvalidOperationException e)
+ {
+ if (e.InnerException is SecurityException == false)
+ throw;
+ }
+
+ return assemblies;
+ });
+ }
+
+ private readonly Lazy> _allAssemblies;
+ private string _rootDir = string.Empty;
+
+ public IEnumerable Assemblies => _allAssemblies.Value;
+
+ // FIXME - this is only an interim change, once the IIOHelper stuff is merged we should use IIOHelper here
+ private string GetRootDirectorySafe()
+ {
+ if (string.IsNullOrEmpty(_rootDir) == false)
+ {
+ return _rootDir;
+ }
+
+ var codeBase = Assembly.GetExecutingAssembly().CodeBase;
+ var uri = new Uri(codeBase);
+ var path = uri.LocalPath;
+ var baseDirectory = Path.GetDirectoryName(path);
+ if (string.IsNullOrEmpty(baseDirectory))
+ throw new PanicException("No root directory could be resolved.");
+
+ _rootDir = baseDirectory.Contains("bin")
+ ? baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin", StringComparison.OrdinalIgnoreCase) - 1)
+ : baseDirectory;
+
+ return _rootDir;
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
new file mode 100644
index 0000000000..1322dcbfa2
--- /dev/null
+++ b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Returns a list of scannable assemblies based on an entry point assembly and it's references
+ ///
+ ///
+ /// This will recursively search through the entry point's assemblies and Umbraco's core assemblies (Core/Web) and their references
+ /// to create a list of scannable assemblies based on whether they themselves or their transitive dependencies reference Umbraco core assemblies.
+ ///
+ public class DefaultUmbracoAssemblyProvider : IAssemblyProvider
+ {
+ private readonly Assembly _entryPointAssembly;
+ private static readonly string[] UmbracoCoreAssemblyNames = new[] { "Umbraco.Core", "Umbraco.Web" };
+
+ public DefaultUmbracoAssemblyProvider(Assembly entryPointAssembly)
+ {
+ _entryPointAssembly = entryPointAssembly ?? throw new ArgumentNullException(nameof(entryPointAssembly));
+ }
+
+ public IEnumerable Assemblies
+ {
+ get
+ {
+ var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, UmbracoCoreAssemblyNames, true);
+ foreach(var found in finder.Find())
+ {
+ yield return found;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs b/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs
new file mode 100644
index 0000000000..91225ff973
--- /dev/null
+++ b/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Finds Assemblies from the entry point assemblies, it's dependencies and it's transitive dependencies that reference that targetAssemblyNames
+ ///
+ ///
+ /// borrowed and modified from here https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/FindAssembliesWithReferencesTo.cs
+ ///
+ internal class FindAssembliesWithReferencesTo
+ {
+ private readonly Assembly[] _referenceAssemblies;
+ private readonly string[] _targetAssemblies;
+ private readonly bool _includeTargets;
+
+ ///
+ /// Constructor
+ ///
+ /// Entry point assemblies
+ /// Used to check if the entry point or it's transitive assemblies reference these assembly names
+ /// If true will also use the target assembly names as entry point assemblies
+ public FindAssembliesWithReferencesTo(Assembly[] referenceAssemblies, string[] targetAssemblyNames, bool includeTargets)
+ {
+ _referenceAssemblies = referenceAssemblies;
+ _targetAssemblies = targetAssemblyNames;
+ _includeTargets = includeTargets;
+ }
+
+ public IEnumerable Find()
+ {
+ var referenceItems = new List();
+ foreach (var assembly in _referenceAssemblies)
+ {
+ referenceItems.Add(assembly);
+ }
+
+ if (_includeTargets)
+ {
+ foreach(var target in _targetAssemblies)
+ {
+ referenceItems.Add(Assembly.Load(target));
+ }
+ }
+
+ var provider = new ReferenceResolver(_targetAssemblies, referenceItems);
+ var assemblyNames = provider.ResolveAssemblies();
+ return assemblyNames.ToList();
+ }
+
+ }
+}
diff --git a/src/Umbraco.Core/Composing/IAssemblyProvider.cs b/src/Umbraco.Core/Composing/IAssemblyProvider.cs
new file mode 100644
index 0000000000..bde97a9556
--- /dev/null
+++ b/src/Umbraco.Core/Composing/IAssemblyProvider.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Provides a list of assemblies that can be scanned
+ ///
+ public interface IAssemblyProvider
+ {
+ IEnumerable Assemblies { get; }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/ReferenceResolver.cs b/src/Umbraco.Core/Composing/ReferenceResolver.cs
new file mode 100644
index 0000000000..6d77afd414
--- /dev/null
+++ b/src/Umbraco.Core/Composing/ReferenceResolver.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Resolves assemblies that reference one of the specified "targetAssemblies" either directly or transitively.
+ ///
+ ///
+ /// Borrowed and modified from https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/ReferenceResolver.cs
+ ///
+ internal class ReferenceResolver
+ {
+ private readonly HashSet _umbracoAssemblies;
+ private readonly IReadOnlyList _assemblyItems;
+ private readonly Dictionary _classifications;
+ private readonly List _lookup = new List();
+
+ public ReferenceResolver(IReadOnlyList targetAssemblies, IReadOnlyList assemblyItems)
+ {
+ _umbracoAssemblies = new HashSet(targetAssemblies, StringComparer.Ordinal);
+ _assemblyItems = assemblyItems;
+ _classifications = new Dictionary();
+
+ foreach (var item in assemblyItems)
+ {
+ _lookup.Add(item);
+ }
+ }
+
+ public IEnumerable ResolveAssemblies()
+ {
+ var applicationParts = new List();
+
+ foreach (var item in _assemblyItems)
+ {
+ var classification = Resolve(item);
+ if (classification == Classification.ReferencesUmbraco || classification == Classification.IsUmbraco)
+ {
+ applicationParts.Add(item);
+ }
+ }
+
+ return applicationParts;
+ }
+
+ private Classification Resolve(Assembly assemblyItem)
+ {
+ if (_classifications.TryGetValue(assemblyItem, out var classification))
+ {
+ return classification;
+ }
+
+ // Initialize the dictionary with a value to short-circuit recursive references.
+ classification = Classification.Unknown;
+ _classifications[assemblyItem] = classification;
+
+ if (_umbracoAssemblies.Contains(assemblyItem.GetName().Name))
+ {
+ classification = Classification.IsUmbraco;
+ }
+ else
+ {
+ classification = Classification.DoesNotReferenceUmbraco;
+ foreach (var reference in GetReferences(assemblyItem))
+ {
+ // recurse
+ var referenceClassification = Resolve(reference);
+
+ if (referenceClassification == Classification.IsUmbraco || referenceClassification == Classification.ReferencesUmbraco)
+ {
+ classification = Classification.ReferencesUmbraco;
+ break;
+ }
+ }
+ }
+
+ Debug.Assert(classification != Classification.Unknown);
+ _classifications[assemblyItem] = classification;
+ return classification;
+ }
+
+ protected virtual IEnumerable GetReferences(Assembly assembly)
+ {
+ foreach (var referenceName in assembly.GetReferencedAssemblies())
+ {
+ // don't include if this is excluded
+ if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => referenceName.FullName.StartsWith(f)))
+ continue;
+
+ var reference = Assembly.Load(referenceName);
+ if (!_lookup.Contains(reference))
+ {
+ // A dependency references an item that isn't referenced by this project.
+ // We'll construct an item for so that we can calculate the classification based on it's name.
+
+ _lookup.Add(reference);
+
+ yield return reference;
+ }
+ }
+ }
+
+ protected enum Classification
+ {
+ Unknown,
+ DoesNotReferenceUmbraco,
+ ReferencesUmbraco,
+ IsUmbraco,
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs
index a0aab7c088..bc15cb63f2 100644
--- a/src/Umbraco.Core/Composing/TypeFinder.cs
+++ b/src/Umbraco.Core/Composing/TypeFinder.cs
@@ -1,16 +1,11 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
using System.Linq;
using System.Reflection;
-using System.Reflection.Metadata;
-using System.Reflection.PortableExecutable;
using System.Security;
using System.Text;
using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Composing
@@ -21,11 +16,6 @@ namespace Umbraco.Core.Composing
private readonly ILogger _logger;
private readonly IAssemblyProvider _assemblyProvider;
- //public TypeFinder(ILogger logger, ITypeFinderConfig typeFinderConfig = null)
- // : this(logger, new DefaultUmbracoAssemblyProvider(Assembly.GetEntryAssembly()?.GetName()?.Name), typeFinderConfig)
- //{
- //}
-
public TypeFinder(ILogger logger, IAssemblyProvider assemblyProvider, ITypeFinderConfig typeFinderConfig = null)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -151,7 +141,9 @@ namespace Umbraco.Core.Composing
"WebDriver,",
"itextsharp,",
"mscorlib,",
- "nunit.framework,",
+ "NUnit,",
+ "NUnit3TestAdapter,",
+ "Selenium.",
};
///
@@ -446,290 +438,4 @@ namespace Umbraco.Core.Composing
#endregion
}
-
- ///
- /// lazily load a reference to all local assemblies and gac assemblies
- ///
- ///
- /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
- ///
- /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
- /// loaded in the CLR, not all assemblies.
- /// See these threads:
- /// http://issues.umbraco.org/issue/U5-198
- /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app
- /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl
- ///
- public class BruteForceAssemblyProvider : IAssemblyProvider
- {
- public BruteForceAssemblyProvider()
- {
- _allAssemblies = new Lazy>(() =>
- {
- HashSet assemblies = null;
- try
- {
- //NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have
- // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one.
- var binFolder = GetRootDirectorySafe();
- var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
- assemblies = new HashSet();
- foreach (var a in binAssemblyFiles)
- {
- try
- {
- var assName = AssemblyName.GetAssemblyName(a);
- var ass = Assembly.Load(assName);
- assemblies.Add(ass);
- }
- catch (Exception e)
- {
- if (e is SecurityException || e is BadImageFormatException)
- {
- //swallow these exceptions
- }
- else
- {
- throw;
- }
- }
- }
-
- //Since we are only loading in the /bin assemblies above, we will also load in anything that's already loaded (which will include gac items)
- foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
- {
- assemblies.Add(a);
- }
- }
- catch (InvalidOperationException e)
- {
- if (e.InnerException is SecurityException == false)
- throw;
- }
-
- return assemblies;
- });
- }
-
- private readonly Lazy> _allAssemblies;
- private string _rootDir = string.Empty;
-
- public IEnumerable Assemblies => _allAssemblies.Value;
-
- // FIXME - this is only an interim change, once the IIOHelper stuff is merged we should use IIOHelper here
- private string GetRootDirectorySafe()
- {
- if (string.IsNullOrEmpty(_rootDir) == false)
- {
- return _rootDir;
- }
-
- var codeBase = Assembly.GetExecutingAssembly().CodeBase;
- var uri = new Uri(codeBase);
- var path = uri.LocalPath;
- var baseDirectory = Path.GetDirectoryName(path);
- if (string.IsNullOrEmpty(baseDirectory))
- throw new PanicException("No root directory could be resolved.");
-
- _rootDir = baseDirectory.Contains("bin")
- ? baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin", StringComparison.OrdinalIgnoreCase) - 1)
- : baseDirectory;
-
- return _rootDir;
- }
- }
-
- ///
- /// Provides a list of assemblies that can be scanned
- ///
- public interface IAssemblyProvider
- {
- IEnumerable Assemblies { get; }
- }
-
- ///
- /// Returns a list of scannable assemblies based on an entry point assembly and it's references
- ///
- ///
- /// This will recursively search through the entry point's assemblies and Umbraco's core assemblies (Core/Web) and their references
- /// to create a list of scannable assemblies based on whether they themselves or their transitive dependencies reference Umbraco core assemblies.
- ///
- public class DefaultUmbracoAssemblyProvider : IAssemblyProvider
- {
- private readonly Assembly _entryPointAssembly;
- private static readonly string[] UmbracoCoreAssemblyNames = new[] { "Umbraco.Core", "Umbraco.Web" };
-
- public DefaultUmbracoAssemblyProvider(Assembly entryPointAssembly)
- {
- _entryPointAssembly = entryPointAssembly ?? throw new ArgumentNullException(nameof(entryPointAssembly));
- }
-
- public IEnumerable Assemblies
- {
- get
- {
- var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, UmbracoCoreAssemblyNames, true);
- foreach(var found in finder.Find())
- {
- yield return found;
- }
- }
- }
- }
-
- ///
- /// Resolves assemblies that reference one of the specified "targetAssemblies" either directly or transitively.
- ///
- ///
- /// Borrowed and modified from https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/ReferenceResolver.cs
- ///
- internal class ReferenceResolver
- {
- private readonly HashSet _umbracoAssemblies;
- private readonly IReadOnlyList _assemblyItems;
- private readonly Dictionary _classifications;
- private readonly List _lookup = new List();
-
- public ReferenceResolver(IReadOnlyList targetAssemblies, IReadOnlyList assemblyItems)
- {
- _umbracoAssemblies = new HashSet(targetAssemblies, StringComparer.Ordinal);
- _assemblyItems = assemblyItems;
- _classifications = new Dictionary();
-
- foreach (var item in assemblyItems)
- {
- _lookup.Add(item);
- }
- }
-
- public IEnumerable ResolveAssemblies()
- {
- var applicationParts = new List();
-
- foreach (var item in _assemblyItems)
- {
- var classification = Resolve(item);
- if (classification == Classification.ReferencesUmbraco || classification == Classification.IsUmbraco)
- {
- applicationParts.Add(item);
- }
- }
-
- return applicationParts;
- }
-
- private Classification Resolve(Assembly assemblyItem)
- {
- if (_classifications.TryGetValue(assemblyItem, out var classification))
- {
- return classification;
- }
-
- // Initialize the dictionary with a value to short-circuit recursive references.
- classification = Classification.Unknown;
- _classifications[assemblyItem] = classification;
-
- if (_umbracoAssemblies.Contains(assemblyItem.GetName().Name))
- {
- classification = Classification.IsUmbraco;
- }
- else
- {
- classification = Classification.DoesNotReferenceUmbraco;
- foreach (var reference in GetReferences(assemblyItem))
- {
- // recurse
- var referenceClassification = Resolve(reference);
-
- if (referenceClassification == Classification.IsUmbraco || referenceClassification == Classification.ReferencesUmbraco)
- {
- classification = Classification.ReferencesUmbraco;
- break;
- }
- }
- }
-
- Debug.Assert(classification != Classification.Unknown);
- _classifications[assemblyItem] = classification;
- return classification;
- }
-
- protected virtual IEnumerable GetReferences(Assembly assembly)
- {
- foreach (var referenceName in assembly.GetReferencedAssemblies())
- {
- // don't include if this is excluded
- if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => referenceName.FullName.StartsWith(f)))
- continue;
-
- var reference = Assembly.Load(referenceName);
- if (!_lookup.Contains(reference))
- {
- // A dependency references an item that isn't referenced by this project.
- // We'll construct an item for so that we can calculate the classification based on it's name.
-
- _lookup.Add(reference);
-
- yield return reference;
- }
- }
- }
-
- protected enum Classification
- {
- Unknown,
- DoesNotReferenceUmbraco,
- ReferencesUmbraco,
- IsUmbraco,
- }
- }
-
-
- ///
- /// Finds Assemblies from the entry point assemblies, it's dependencies and it's transitive dependencies that reference that targetAssemblyNames
- ///
- ///
- /// borrowed and modified from here https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/FindAssembliesWithReferencesTo.cs
- ///
- internal class FindAssembliesWithReferencesTo
- {
- private readonly Assembly[] _referenceAssemblies;
- private readonly string[] _targetAssemblies;
- private readonly bool _includeTargets;
-
- ///
- /// Constructor
- ///
- /// Entry point assemblies
- /// Used to check if the entry point or it's transitive assemblies reference these assembly names
- /// If true will also use the target assembly names as entry point assemblies
- public FindAssembliesWithReferencesTo(Assembly[] referenceAssemblies, string[] targetAssemblyNames, bool includeTargets)
- {
- _referenceAssemblies = referenceAssemblies;
- _targetAssemblies = targetAssemblyNames;
- _includeTargets = includeTargets;
- }
-
- public IEnumerable Find()
- {
- var referenceItems = new List();
- foreach (var assembly in _referenceAssemblies)
- {
- referenceItems.Add(assembly);
- }
-
- if (_includeTargets)
- {
- foreach(var target in _targetAssemblies)
- {
- referenceItems.Add(Assembly.Load(target));
- }
- }
-
- var provider = new ReferenceResolver(_targetAssemblies, referenceItems);
- var assemblyNames = provider.ResolveAssemblies();
- return assemblyNames.ToList();
- }
-
- }
}
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 49d5090070..7a15e7fbed 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -13,7 +13,6 @@
-
diff --git a/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs b/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs
index dec895a432..e4844cc6be 100644
--- a/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs
+++ b/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs
@@ -13,6 +13,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Tests.Collections;
+using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Cache;
namespace Umbraco.Tests.Cache
@@ -28,7 +29,7 @@ namespace Umbraco.Tests.Cache
public override void Setup()
{
base.Setup();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
_memberCache = new ObjectCacheAppCache(typeFinder);
_provider = new DeepCloneAppCache(_memberCache);
diff --git a/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs
index 28d9b42ab0..dbda6fb429 100644
--- a/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs
+++ b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs
@@ -16,7 +16,7 @@ namespace Umbraco.Tests.Cache
public override void Setup()
{
base.Setup();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
_ctx = new FakeHttpContextFactory("http://localhost/test");
_appCache = new HttpRequestAppCache(() => _ctx.HttpContext.Items, typeFinder);
}
diff --git a/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs b/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs
index e8fc420f58..7957026ad8 100644
--- a/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs
+++ b/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs
@@ -1,10 +1,7 @@
-using System.Collections.Generic;
-using System.Linq;
-using Moq;
+using System.Linq;
using NUnit.Framework;
using Umbraco.Core.Cache;
-using Umbraco.Core.Composing;
-using Umbraco.Core.Logging;
+using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Cache
{
@@ -21,7 +18,7 @@ namespace Umbraco.Tests.Cache
public override void Setup()
{
base.Setup();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
_provider = new ObjectCacheAppCache(typeFinder);
}
diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs
index 0b179d6d85..cf54b8e9ec 100644
--- a/src/Umbraco.Tests/Components/ComponentTests.cs
+++ b/src/Umbraco.Tests/Components/ComponentTests.cs
@@ -32,7 +32,7 @@ namespace Umbraco.Tests.Components
var mock = new Mock();
var logger = Mock.Of();
- var typeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(typeof(ComponentTests).Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var f = new UmbracoDatabaseFactory(logger, new Lazy(() => new MapperCollection(Enumerable.Empty())), TestHelper.GetConfigs(), TestHelper.DbProviderFactoryCreator);
var fs = new FileSystems(mock.Object, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings());
var coreDebug = Mock.Of();
@@ -371,7 +371,7 @@ namespace Umbraco.Tests.Components
public void AllComposers()
{
var ioHelper = TestHelper.IOHelper;
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var typeLoader = new TypeLoader(ioHelper, typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), Mock.Of());
var register = MockRegister();
diff --git a/src/Umbraco.Tests/Composing/ComposingTestBase.cs b/src/Umbraco.Tests/Composing/ComposingTestBase.cs
index 5e90b777fe..6c5ccd5510 100644
--- a/src/Umbraco.Tests/Composing/ComposingTestBase.cs
+++ b/src/Umbraco.Tests/Composing/ComposingTestBase.cs
@@ -22,7 +22,7 @@ namespace Umbraco.Tests.Composing
{
ProfilingLogger = new ProfilingLogger(Mock.Of(), Mock.Of());
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ 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);
}
diff --git a/src/Umbraco.Tests/Composing/CompositionTests.cs b/src/Umbraco.Tests/Composing/CompositionTests.cs
index 7a71afa625..ce3cdfac17 100644
--- a/src/Umbraco.Tests/Composing/CompositionTests.cs
+++ b/src/Umbraco.Tests/Composing/CompositionTests.cs
@@ -38,7 +38,7 @@ namespace Umbraco.Tests.Composing
.Returns(() => factoryFactory?.Invoke(mockedFactory));
var logger = new ProfilingLogger(Mock.Of(), Mock.Of());
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var ioHelper = TestHelper.IOHelper;
var typeLoader = new TypeLoader(ioHelper, typeFinder, Mock.Of(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), logger);
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of(), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache);
diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs
index 7d68f616fa..d0181563a8 100644
--- a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs
+++ b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs
@@ -27,7 +27,7 @@ namespace Umbraco.Tests.Composing
public void Initialize()
{
// this ensures it's reset
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
_typeLoader = new TypeLoader(TestHelper.IOHelper, typeFinder, NoAppCache.Instance,
new DirectoryInfo(TestHelper.IOHelper.MapPath("~/App_Data/TEMP")),
new ProfilingLogger(Mock.Of(), Mock.Of()), false,
diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs
index addc5afde0..d6ed8f33c2 100644
--- a/src/Umbraco.Tests/Macros/MacroTests.cs
+++ b/src/Umbraco.Tests/Macros/MacroTests.cs
@@ -17,7 +17,7 @@ namespace Umbraco.Tests.Macros
[SetUp]
public void Setup()
{
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
//we DO want cache enabled for these tests
var cacheHelper = new AppCaches(
new ObjectCacheAppCache(typeFinder),
diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs
index c25197d79e..e33f707ee1 100644
--- a/src/Umbraco.Tests/Models/ContentTests.cs
+++ b/src/Umbraco.Tests/Models/ContentTests.cs
@@ -22,6 +22,7 @@ using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Tests.Testing;
using Umbraco.Web.PropertyEditors;
+using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Models
{
@@ -269,7 +270,8 @@ namespace Umbraco.Tests.Models
content.UpdateDate = DateTime.Now;
content.WriterId = 23;
- var runtimeCache = new ObjectCacheAppCache(new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly)));
+ var typeFinder = TestHelper.GetTypeFinder();
+ var runtimeCache = new ObjectCacheAppCache(typeFinder);
runtimeCache.Insert(content.Id.ToString(CultureInfo.InvariantCulture), () => content);
var proflog = GetTestProfilingLogger();
diff --git a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs
index d0c348bc0c..769985d515 100644
--- a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs
+++ b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs
@@ -127,7 +127,7 @@ namespace Umbraco.Tests.Published
var setType1 = publishedContentTypeFactory.CreateContentType(1000, "set1", CreatePropertyTypes);
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var elementsCache = new FastDictionaryAppCache(typeFinder);
var snapshotCache = new FastDictionaryAppCache(typeFinder);
diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs
index 9947f76fb0..e8296320a5 100644
--- a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs
+++ b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs
@@ -143,7 +143,7 @@ namespace Umbraco.Tests.PublishedContent
// create a data source for NuCache
_source = new TestDataSource(kits);
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var settings = Mock.Of();
diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs
index be2ba1b48b..1f6895296f 100644
--- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs
+++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs
@@ -184,7 +184,7 @@ namespace Umbraco.Tests.PublishedContent
// create a variation accessor
_variationAccesor = new TestVariationContextAccessor();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var settings = Mock.Of();
// at last, create the complete NuCache snapshot service!
diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
index 2bcfd2d98b..ecc5094166 100644
--- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
+++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
@@ -256,7 +256,7 @@ namespace Umbraco.Tests.Runtimes
var profilingLogger = new ProfilingLogger(logger, profiler);
var appCaches = AppCaches.Disabled;
var databaseFactory = Mock.Of();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ 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 runtimeState = Mock.Of();
diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs
index b2252e705d..aada99da71 100644
--- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs
+++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs
@@ -85,7 +85,7 @@ namespace Umbraco.Tests.Scoping
var memberRepository = Mock.Of();
var hostingEnvironment = TestHelper.GetHostingEnvironment();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var settings = Mock.Of();
return new PublishedSnapshotService(
diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs
index a8d045c5e8..33e8b0010e 100644
--- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs
+++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs
@@ -58,7 +58,7 @@ namespace Umbraco.Tests.Services
var memberRepository = Mock.Of();
var hostingEnvironment = Mock.Of();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var settings = Mock.Of();
return new PublishedSnapshotService(
diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs
index 19b45c8ad5..e035eaa807 100644
--- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs
+++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs
@@ -38,7 +38,7 @@ namespace Umbraco.Tests.TestHelpers
var ioHelper = TestHelper.IOHelper;
var logger = new ProfilingLogger(Mock.Of(), Mock.Of());
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var typeLoader = new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance,
new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")),
logger,
diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs
index b2650695ac..f5d18e05ba 100644
--- a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs
+++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.TestHelpers.Stubs
{
if (_factory != null) return _factory(requestContext);
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var types = typeFinder.FindClassesOfType(new[] { Assembly.GetExecutingAssembly() });
var controllerTypes = types.Where(x => x.Name.Equals(controllerName + "Controller", StringComparison.InvariantCultureIgnoreCase));
diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
index 41b97ac580..177fc2d518 100644
--- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
@@ -43,6 +43,12 @@ namespace Umbraco.Tests.TestHelpers
public static class TestHelper
{
+ public static ITypeFinder GetTypeFinder()
+ {
+ var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(typeof(TestHelper).Assembly));
+ return typeFinder;
+ }
+
public static TypeLoader GetMockedTypeLoader()
{
return new TypeLoader(IOHelper, Mock.Of(), Mock.Of(), new DirectoryInfo(IOHelper.MapPath("~/App_Data/TEMP")), Mock.Of());
diff --git a/src/Umbraco.Tests/Web/UmbracoHelperTests.cs b/src/Umbraco.Tests/Web/UmbracoHelperTests.cs
index 7846bf366b..62d7e941d7 100644
--- a/src/Umbraco.Tests/Web/UmbracoHelperTests.cs
+++ b/src/Umbraco.Tests/Web/UmbracoHelperTests.cs
@@ -28,7 +28,7 @@ namespace Umbraco.Tests.Web
{
// FIXME: bad in a unit test - but Udi has a static ctor that wants it?!
var container = new Mock();
- var typeFinder = new TypeFinder(Mock.Of(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
+ var typeFinder = TestHelper.GetTypeFinder();
var ioHelper = TestHelper.IOHelper;
container
.Setup(x => x.GetInstance(typeof(TypeLoader)))
diff --git a/src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs b/src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs
new file mode 100644
index 0000000000..3c5cebe03e
--- /dev/null
+++ b/src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Security;
+using System.Web.Compilation;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
+
+namespace Umbraco.Web.Composing
+{
+ ///
+ /// Uses the BuildManager to provide a list of assemblies to scan
+ ///
+ internal class BuildManagerAssemblyProvider : BruteForceAssemblyProvider, IAssemblyProvider
+ {
+ private readonly Lazy> _allAssemblies;
+
+ public BuildManagerAssemblyProvider(IIOHelper ioHelper,
+ IHostingEnvironment hostingEnvironment,
+ ILogger logger)
+ {
+ _allAssemblies = new Lazy>(() =>
+ {
+ var isHosted = hostingEnvironment.IsHosted;
+ try
+ {
+ if (isHosted)
+ {
+ var assemblies = new HashSet(BuildManager.GetReferencedAssemblies().Cast());
+
+ //here we are trying to get the App_Code assembly
+ var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported
+ var appCodeFolder = new DirectoryInfo(ioHelper.MapPath(ioHelper.ResolveUrl("~/App_code")));
+ //check if the folder exists and if there are any files in it with the supported file extensions
+ if (appCodeFolder.Exists && fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))
+ {
+ try
+ {
+ var appCodeAssembly = Assembly.Load("App_Code");
+ if (assemblies.Contains(appCodeAssembly) == false) // BuildManager will find App_Code already
+ assemblies.Add(appCodeAssembly);
+ }
+ catch (FileNotFoundException ex)
+ {
+ //this will occur if it cannot load the assembly
+ logger.Error(typeof(TypeFinder), ex, "Could not load assembly App_Code");
+ }
+ }
+
+ return assemblies;
+ }
+ }
+ catch (InvalidOperationException e)
+ {
+ if (e.InnerException is SecurityException == false)
+ throw;
+ }
+
+ // Not hosted, just use the default implementation
+ return new HashSet(base.Assemblies);
+ });
+ }
+
+ IEnumerable IAssemblyProvider.Assemblies => _allAssemblies.Value;
+ }
+}
diff --git a/src/Umbraco.Web/Composing/BuildManagerTypeFinder.cs b/src/Umbraco.Web/Composing/BuildManagerTypeFinder.cs
index bd583bf29d..d3502c36fb 100644
--- a/src/Umbraco.Web/Composing/BuildManagerTypeFinder.cs
+++ b/src/Umbraco.Web/Composing/BuildManagerTypeFinder.cs
@@ -1,19 +1,15 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
-using System.Reflection;
-using System.Security;
using System.Web.Compilation;
using Umbraco.Core.Configuration;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Core.Hosting;
-using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Web.Composing
{
+
///
/// An implementation of TypeFinder that uses the BuildManager to resolve references for aspnet framework hosted websites
///
@@ -24,60 +20,13 @@ namespace Umbraco.Web.Composing
{
public BuildManagerTypeFinder(
- IIOHelper ioHelper,
- IHostingEnvironment hostingEnvironment,
ILogger logger,
IAssemblyProvider assemblyProvider,
ITypeFinderConfig typeFinderConfig = null) : base(logger, assemblyProvider, typeFinderConfig)
{
- if (ioHelper == null) throw new ArgumentNullException(nameof(ioHelper));
- if (hostingEnvironment == null) throw new ArgumentNullException(nameof(hostingEnvironment));
if (logger == null) throw new ArgumentNullException(nameof(logger));
-
- _allAssemblies = new Lazy>(() =>
- {
- var isHosted = hostingEnvironment.IsHosted;
- try
- {
- if (isHosted)
- {
- var assemblies = new HashSet(BuildManager.GetReferencedAssemblies().Cast());
-
- //here we are trying to get the App_Code assembly
- var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported
- var appCodeFolder = new DirectoryInfo(ioHelper.MapPath(ioHelper.ResolveUrl("~/App_code")));
- //check if the folder exists and if there are any files in it with the supported file extensions
- if (appCodeFolder.Exists && fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))
- {
- try
- {
- var appCodeAssembly = Assembly.Load("App_Code");
- if (assemblies.Contains(appCodeAssembly) == false) // BuildManager will find App_Code already
- assemblies.Add(appCodeAssembly);
- }
- catch (FileNotFoundException ex)
- {
- //this will occur if it cannot load the assembly
- logger.Error(typeof(TypeFinder), ex, "Could not load assembly App_Code");
- }
- }
-
- return assemblies;
- }
- }
- catch (InvalidOperationException e)
- {
- if (e.InnerException is SecurityException == false)
- throw;
- }
-
- // Not hosted, just use the default implementation
- return new HashSet(base.AssembliesToScan);
- });
}
- private readonly Lazy> _allAssemblies;
-
///
/// Explicitly implement and return result from BuildManager
///
@@ -85,10 +34,6 @@ namespace Umbraco.Web.Composing
///
Type ITypeFinder.GetTypeByName (string name) => BuildManager.GetType(name, false);
- ///
- /// Explicitly implement and return result from BuildManager
- ///
- IEnumerable ITypeFinder.AssembliesToScan => _allAssemblies.Value;
///
/// TypeFinder config via appSettings
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index fad79b0296..27ea9443a0 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -143,6 +143,7 @@
+