diff --git a/src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs b/src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs deleted file mode 100644 index 04d0d70475..0000000000 --- a/src/Umbraco.Core/Composing/BruteForceAssemblyProvider.cs +++ /dev/null @@ -1,102 +0,0 @@ -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/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs index 27b13a8365..ee900756c8 100644 --- a/src/Umbraco.Core/Composing/TypeFinder.cs +++ b/src/Umbraco.Core/Composing/TypeFinder.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Logging; namespace Umbraco.Core.Composing { + /// public class TypeFinder : ITypeFinder { @@ -212,6 +213,11 @@ namespace Umbraco.Core.Composing /// public virtual Type GetTypeByName(string name) { + + //NOTE: This will not find types in dynamic assemblies unless those assemblies are already loaded + //into the appdomain. + + // This is exactly what the BuildManager does, if the type is an assembly qualified type // name it will find it. if (TypeNameContainsAssembly(name)) diff --git a/src/Umbraco.Core/Composing/TypeFinderConfig.cs b/src/Umbraco.Core/Composing/TypeFinderConfig.cs new file mode 100644 index 0000000000..3dc672b27c --- /dev/null +++ b/src/Umbraco.Core/Composing/TypeFinderConfig.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; + +namespace Umbraco.Core.Composing +{ + /// + /// TypeFinder config via appSettings + /// + internal class TypeFinderConfig : ITypeFinderConfig + { + private readonly ITypeFinderSettings _settings; + private IEnumerable _assembliesAcceptingLoadExceptions; + + public TypeFinderConfig(ITypeFinderSettings settings) + { + _settings = settings; + } + + public IEnumerable AssembliesAcceptingLoadExceptions + { + get + { + if (_assembliesAcceptingLoadExceptions != null) + return _assembliesAcceptingLoadExceptions; + + var s = _settings.AssembliesAcceptingLoadExceptions; + return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s) + ? Array.Empty() + : s.Split(',').Select(x => x.Trim()).ToArray(); + } + } + } +} diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index e12a81be36..39f5a4209f 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -370,6 +370,8 @@ namespace Umbraco.Core.Runtime /// /// protected virtual ITypeFinder GetTypeFinder() + // TODO: Currently we are not passing in any TypeFinderConfig (with ITypeFinderSettings) which we should do, however + // this is not critical right now and would require loading in some config before boot time so just leaving this as-is for now. => new TypeFinder(Logger, new DefaultUmbracoAssemblyProvider(Assembly.GetEntryAssembly())); diff --git a/src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs b/src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs deleted file mode 100644 index 3c5cebe03e..0000000000 --- a/src/Umbraco.Web/Composing/BuildManagerAssemblyProvider.cs +++ /dev/null @@ -1,70 +0,0 @@ -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 deleted file mode 100644 index d3502c36fb..0000000000 --- a/src/Umbraco.Web/Composing/BuildManagerTypeFinder.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Compilation; -using Umbraco.Core.Configuration; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Logging; - -namespace Umbraco.Web.Composing -{ - - /// - /// An implementation of TypeFinder that uses the BuildManager to resolve references for aspnet framework hosted websites - /// - /// - /// This finder will also try to resolve dynamic assemblies created from App_Code - /// - internal class BuildManagerTypeFinder : TypeFinder, ITypeFinder - { - - public BuildManagerTypeFinder( - ILogger logger, - IAssemblyProvider assemblyProvider, - ITypeFinderConfig typeFinderConfig = null) : base(logger, assemblyProvider, typeFinderConfig) - { - if (logger == null) throw new ArgumentNullException(nameof(logger)); - } - - /// - /// Explicitly implement and return result from BuildManager - /// - /// - /// - Type ITypeFinder.GetTypeByName (string name) => BuildManager.GetType(name, false); - - - /// - /// TypeFinder config via appSettings - /// - internal class TypeFinderConfig : ITypeFinderConfig - { - private readonly ITypeFinderSettings _settings; - private IEnumerable _assembliesAcceptingLoadExceptions; - - public TypeFinderConfig(ITypeFinderSettings settings) - { - _settings = settings; - } - - public IEnumerable AssembliesAcceptingLoadExceptions - { - get - { - if (_assembliesAcceptingLoadExceptions != null) - return _assembliesAcceptingLoadExceptions; - - var s = _settings.AssembliesAcceptingLoadExceptions; - return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s) - ? Array.Empty() - : s.Split(',').Select(x => x.Trim()).ToArray(); - } - } - } - } -} diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 5fab9ff9d4..ea08dc9135 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -21,8 +21,6 @@ namespace Umbraco.Web.Runtime /// On top of CoreRuntime, handles all of the web-related runtime aspects of Umbraco. public class WebRuntime : CoreRuntime { - private BuildManagerTypeFinder _typeFinder; - /// /// Initializes a new instance of the class. /// @@ -92,8 +90,6 @@ namespace Umbraco.Web.Runtime #region Getters - //protected override ITypeFinder GetTypeFinder() => _typeFinder ?? (_typeFinder = new BuildManagerTypeFinder(IOHelper, HostingEnvironment, Logger, new BuildManagerTypeFinder.TypeFinderConfig(new TypeFinderSettings()))); - 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) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 27ea9443a0..e9a4e04e58 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -143,8 +143,6 @@ - -