More cleanup, cleans up tests, cleans up the BuildManagerAssemblyProvider (even though it's not used)
This commit is contained in:
102
src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs
Normal file
102
src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// lazily load a reference to all local assemblies and gac assemblies
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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
|
||||
/// </remarks>
|
||||
public class BruteForceAssemblyProvider : IAssemblyProvider
|
||||
{
|
||||
public BruteForceAssemblyProvider()
|
||||
{
|
||||
_allAssemblies = new Lazy<HashSet<Assembly>>(() =>
|
||||
{
|
||||
HashSet<Assembly> 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<Assembly>();
|
||||
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<HashSet<Assembly>> _allAssemblies;
|
||||
private string _rootDir = string.Empty;
|
||||
|
||||
public IEnumerable<Assembly> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
Normal file
36
src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of scannable assemblies based on an entry point assembly and it's references
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
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<Assembly> Assemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, UmbracoCoreAssemblyNames, true);
|
||||
foreach(var found in finder.Find())
|
||||
{
|
||||
yield return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs
Normal file
55
src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Finds Assemblies from the entry point assemblies, it's dependencies and it's transitive dependencies that reference that targetAssemblyNames
|
||||
/// </summary>
|
||||
/// <remarkes>
|
||||
/// borrowed and modified from here https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/FindAssembliesWithReferencesTo.cs
|
||||
/// </remarkes>
|
||||
internal class FindAssembliesWithReferencesTo
|
||||
{
|
||||
private readonly Assembly[] _referenceAssemblies;
|
||||
private readonly string[] _targetAssemblies;
|
||||
private readonly bool _includeTargets;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="referenceAssemblies">Entry point assemblies</param>
|
||||
/// <param name="targetAssemblyNames">Used to check if the entry point or it's transitive assemblies reference these assembly names</param>
|
||||
/// <param name="includeTargets">If true will also use the target assembly names as entry point assemblies</param>
|
||||
public FindAssembliesWithReferencesTo(Assembly[] referenceAssemblies, string[] targetAssemblyNames, bool includeTargets)
|
||||
{
|
||||
_referenceAssemblies = referenceAssemblies;
|
||||
_targetAssemblies = targetAssemblyNames;
|
||||
_includeTargets = includeTargets;
|
||||
}
|
||||
|
||||
public IEnumerable<Assembly> Find()
|
||||
{
|
||||
var referenceItems = new List<Assembly>();
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
13
src/Umbraco.Core/Composing/IAssemblyProvider.cs
Normal file
13
src/Umbraco.Core/Composing/IAssemblyProvider.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a list of assemblies that can be scanned
|
||||
/// </summary>
|
||||
public interface IAssemblyProvider
|
||||
{
|
||||
IEnumerable<Assembly> Assemblies { get; }
|
||||
}
|
||||
}
|
||||
115
src/Umbraco.Core/Composing/ReferenceResolver.cs
Normal file
115
src/Umbraco.Core/Composing/ReferenceResolver.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves assemblies that reference one of the specified "targetAssemblies" either directly or transitively.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Borrowed and modified from https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/ReferenceResolver.cs
|
||||
/// </remarks>
|
||||
internal class ReferenceResolver
|
||||
{
|
||||
private readonly HashSet<string> _umbracoAssemblies;
|
||||
private readonly IReadOnlyList<Assembly> _assemblyItems;
|
||||
private readonly Dictionary<Assembly, Classification> _classifications;
|
||||
private readonly List<Assembly> _lookup = new List<Assembly>();
|
||||
|
||||
public ReferenceResolver(IReadOnlyList<string> targetAssemblies, IReadOnlyList<Assembly> assemblyItems)
|
||||
{
|
||||
_umbracoAssemblies = new HashSet<string>(targetAssemblies, StringComparer.Ordinal);
|
||||
_assemblyItems = assemblyItems;
|
||||
_classifications = new Dictionary<Assembly, Classification>();
|
||||
|
||||
foreach (var item in assemblyItems)
|
||||
{
|
||||
_lookup.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Assembly> ResolveAssemblies()
|
||||
{
|
||||
var applicationParts = new List<Assembly>();
|
||||
|
||||
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<Assembly> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -446,290 +438,4 @@ namespace Umbraco.Core.Composing
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// lazily load a reference to all local assemblies and gac assemblies
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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
|
||||
/// </remarks>
|
||||
public class BruteForceAssemblyProvider : IAssemblyProvider
|
||||
{
|
||||
public BruteForceAssemblyProvider()
|
||||
{
|
||||
_allAssemblies = new Lazy<HashSet<Assembly>>(() =>
|
||||
{
|
||||
HashSet<Assembly> 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<Assembly>();
|
||||
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<HashSet<Assembly>> _allAssemblies;
|
||||
private string _rootDir = string.Empty;
|
||||
|
||||
public IEnumerable<Assembly> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a list of assemblies that can be scanned
|
||||
/// </summary>
|
||||
public interface IAssemblyProvider
|
||||
{
|
||||
IEnumerable<Assembly> Assemblies { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of scannable assemblies based on an entry point assembly and it's references
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
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<Assembly> Assemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, UmbracoCoreAssemblyNames, true);
|
||||
foreach(var found in finder.Find())
|
||||
{
|
||||
yield return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves assemblies that reference one of the specified "targetAssemblies" either directly or transitively.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Borrowed and modified from https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/ReferenceResolver.cs
|
||||
/// </remarks>
|
||||
internal class ReferenceResolver
|
||||
{
|
||||
private readonly HashSet<string> _umbracoAssemblies;
|
||||
private readonly IReadOnlyList<Assembly> _assemblyItems;
|
||||
private readonly Dictionary<Assembly, Classification> _classifications;
|
||||
private readonly List<Assembly> _lookup = new List<Assembly>();
|
||||
|
||||
public ReferenceResolver(IReadOnlyList<string> targetAssemblies, IReadOnlyList<Assembly> assemblyItems)
|
||||
{
|
||||
_umbracoAssemblies = new HashSet<string>(targetAssemblies, StringComparer.Ordinal);
|
||||
_assemblyItems = assemblyItems;
|
||||
_classifications = new Dictionary<Assembly, Classification>();
|
||||
|
||||
foreach (var item in assemblyItems)
|
||||
{
|
||||
_lookup.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Assembly> ResolveAssemblies()
|
||||
{
|
||||
var applicationParts = new List<Assembly>();
|
||||
|
||||
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<Assembly> 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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds Assemblies from the entry point assemblies, it's dependencies and it's transitive dependencies that reference that targetAssemblyNames
|
||||
/// </summary>
|
||||
/// <remarkes>
|
||||
/// borrowed and modified from here https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/FindAssembliesWithReferencesTo.cs
|
||||
/// </remarkes>
|
||||
internal class FindAssembliesWithReferencesTo
|
||||
{
|
||||
private readonly Assembly[] _referenceAssemblies;
|
||||
private readonly string[] _targetAssemblies;
|
||||
private readonly bool _includeTargets;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="referenceAssemblies">Entry point assemblies</param>
|
||||
/// <param name="targetAssemblyNames">Used to check if the entry point or it's transitive assemblies reference these assembly names</param>
|
||||
/// <param name="includeTargets">If true will also use the target assembly names as entry point assemblies</param>
|
||||
public FindAssembliesWithReferencesTo(Assembly[] referenceAssemblies, string[] targetAssemblyNames, bool includeTargets)
|
||||
{
|
||||
_referenceAssemblies = referenceAssemblies;
|
||||
_targetAssemblies = targetAssemblyNames;
|
||||
_includeTargets = includeTargets;
|
||||
}
|
||||
|
||||
public IEnumerable<Assembly> Find()
|
||||
{
|
||||
var referenceItems = new List<Assembly>();
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.6.0" />
|
||||
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="1.8.0" />
|
||||
<PackageReference Include="System.Runtime.Caching" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -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<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
_memberCache = new ObjectCacheAppCache(typeFinder);
|
||||
|
||||
_provider = new DeepCloneAppCache(_memberCache);
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Tests.Cache
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
_ctx = new FakeHttpContextFactory("http://localhost/test");
|
||||
_appCache = new HttpRequestAppCache(() => _ctx.HttpContext.Items, typeFinder);
|
||||
}
|
||||
|
||||
@@ -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<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
_provider = new ObjectCacheAppCache(typeFinder);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Tests.Components
|
||||
var mock = new Mock<IFactory>();
|
||||
|
||||
var logger = Mock.Of<ILogger>();
|
||||
var typeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(typeof(ComponentTests).Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var f = new UmbracoDatabaseFactory(logger, new Lazy<IMapperCollection>(() => new MapperCollection(Enumerable.Empty<BaseMapper>())), TestHelper.GetConfigs(), TestHelper.DbProviderFactoryCreator);
|
||||
var fs = new FileSystems(mock.Object, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings());
|
||||
var coreDebug = Mock.Of<ICoreDebug>();
|
||||
@@ -371,7 +371,7 @@ namespace Umbraco.Tests.Components
|
||||
public void AllComposers()
|
||||
{
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), 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<IProfilingLogger>());
|
||||
|
||||
var register = MockRegister();
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Tests.Composing
|
||||
{
|
||||
ProfilingLogger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
|
||||
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), 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);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Tests.Composing
|
||||
.Returns(() => factoryFactory?.Invoke(mockedFactory));
|
||||
|
||||
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, Mock.Of<IAppPolicyCache>(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), logger);
|
||||
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of<IRuntimeState>(), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Tests.Composing
|
||||
public void Initialize()
|
||||
{
|
||||
// this ensures it's reset
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), 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<ILogger>(), Mock.Of<IProfiler>()), false,
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Tests.Macros
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
//we DO want cache enabled for these tests
|
||||
var cacheHelper = new AppCaches(
|
||||
new ObjectCacheAppCache(typeFinder),
|
||||
|
||||
@@ -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<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly)));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var runtimeCache = new ObjectCacheAppCache(typeFinder);
|
||||
runtimeCache.Insert(content.Id.ToString(CultureInfo.InvariantCulture), () => content);
|
||||
|
||||
var proflog = GetTestProfilingLogger();
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace Umbraco.Tests.Published
|
||||
|
||||
var setType1 = publishedContentTypeFactory.CreateContentType(1000, "set1", CreatePropertyTypes);
|
||||
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var elementsCache = new FastDictionaryAppCache(typeFinder);
|
||||
var snapshotCache = new FastDictionaryAppCache(typeFinder);
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
// create a data source for NuCache
|
||||
_source = new TestDataSource(kits);
|
||||
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var settings = Mock.Of<INuCacheSettings>();
|
||||
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
// create a variation accessor
|
||||
_variationAccesor = new TestVariationContextAccessor();
|
||||
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var settings = Mock.Of<INuCacheSettings>();
|
||||
|
||||
// at last, create the complete NuCache snapshot service!
|
||||
|
||||
@@ -256,7 +256,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
var profilingLogger = new ProfilingLogger(logger, profiler);
|
||||
var appCaches = AppCaches.Disabled;
|
||||
var databaseFactory = Mock.Of<IUmbracoDatabaseFactory>();
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), 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<IRuntimeState>();
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Umbraco.Tests.Scoping
|
||||
var memberRepository = Mock.Of<IMemberRepository>();
|
||||
var hostingEnvironment = TestHelper.GetHostingEnvironment();
|
||||
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var settings = Mock.Of<INuCacheSettings>();
|
||||
|
||||
return new PublishedSnapshotService(
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Tests.Services
|
||||
var memberRepository = Mock.Of<IMemberRepository>();
|
||||
var hostingEnvironment = Mock.Of<IHostingEnvironment>();
|
||||
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var settings = Mock.Of<INuCacheSettings>();
|
||||
|
||||
return new PublishedSnapshotService(
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance,
|
||||
new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")),
|
||||
logger,
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.TestHelpers.Stubs
|
||||
{
|
||||
if (_factory != null) return _factory(requestContext);
|
||||
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var types = typeFinder.FindClassesOfType<ControllerBase>(new[] { Assembly.GetExecutingAssembly() });
|
||||
|
||||
var controllerTypes = types.Where(x => x.Name.Equals(controllerName + "Controller", StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
@@ -43,6 +43,12 @@ namespace Umbraco.Tests.TestHelpers
|
||||
public static class TestHelper
|
||||
{
|
||||
|
||||
public static ITypeFinder GetTypeFinder()
|
||||
{
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(typeof(TestHelper).Assembly));
|
||||
return typeFinder;
|
||||
}
|
||||
|
||||
public static TypeLoader GetMockedTypeLoader()
|
||||
{
|
||||
return new TypeLoader(IOHelper, Mock.Of<ITypeFinder>(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(IOHelper.MapPath("~/App_Data/TEMP")), Mock.Of<IProfilingLogger>());
|
||||
|
||||
@@ -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<IFactory>();
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
container
|
||||
.Setup(x => x.GetInstance(typeof(TypeLoader)))
|
||||
|
||||
70
src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs
Normal file
70
src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Uses the BuildManager to provide a list of assemblies to scan
|
||||
/// </summary>
|
||||
internal class BuildManagerAssemblyProvider : BruteForceAssemblyProvider, IAssemblyProvider
|
||||
{
|
||||
private readonly Lazy<HashSet<Assembly>> _allAssemblies;
|
||||
|
||||
public BuildManagerAssemblyProvider(IIOHelper ioHelper,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
ILogger logger)
|
||||
{
|
||||
_allAssemblies = new Lazy<HashSet<Assembly>>(() =>
|
||||
{
|
||||
var isHosted = hostingEnvironment.IsHosted;
|
||||
try
|
||||
{
|
||||
if (isHosted)
|
||||
{
|
||||
var assemblies = new HashSet<Assembly>(BuildManager.GetReferencedAssemblies().Cast<Assembly>());
|
||||
|
||||
//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<Assembly>(base.Assemblies);
|
||||
});
|
||||
}
|
||||
|
||||
IEnumerable<Assembly> IAssemblyProvider.Assemblies => _allAssemblies.Value;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An implementation of TypeFinder that uses the BuildManager to resolve references for aspnet framework hosted websites
|
||||
/// </summary>
|
||||
@@ -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<HashSet<Assembly>>(() =>
|
||||
{
|
||||
var isHosted = hostingEnvironment.IsHosted;
|
||||
try
|
||||
{
|
||||
if (isHosted)
|
||||
{
|
||||
var assemblies = new HashSet<Assembly>(BuildManager.GetReferencedAssemblies().Cast<Assembly>());
|
||||
|
||||
//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<Assembly>(base.AssembliesToScan);
|
||||
});
|
||||
}
|
||||
|
||||
private readonly Lazy<HashSet<Assembly>> _allAssemblies;
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly implement and return result from BuildManager
|
||||
/// </summary>
|
||||
@@ -85,10 +34,6 @@ namespace Umbraco.Web.Composing
|
||||
/// <returns></returns>
|
||||
Type ITypeFinder.GetTypeByName (string name) => BuildManager.GetType(name, false);
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly implement and return result from BuildManager
|
||||
/// </summary>
|
||||
IEnumerable<Assembly> ITypeFinder.AssembliesToScan => _allAssemblies.Value;
|
||||
|
||||
/// <summary>
|
||||
/// TypeFinder config via appSettings
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
<Compile Include="Compose\AuditEventsComposer.cs" />
|
||||
<Compile Include="Compose\BackOfficeUserAuditEventsComponent.cs" />
|
||||
<Compile Include="Compose\BackOfficeUserAuditEventsComposer.cs" />
|
||||
<Compile Include="Composing\BuildManagerAssemblyProvider.cs" />
|
||||
<Compile Include="Composing\BuildManagerTypeFinder.cs" />
|
||||
<Compile Include="Composing\CompositionExtensions\Installer.cs" />
|
||||
<Compile Include="Composing\LightInject\LightInjectContainer.cs" />
|
||||
|
||||
Reference in New Issue
Block a user