using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Extensions.Logging; namespace Umbraco.Cms.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 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 readonly ILoggerFactory _loggerFactory; private readonly IEnumerable _additionalTargetAssemblies; private List _discovered; public DefaultUmbracoAssemblyProvider( Assembly entryPointAssembly, ILoggerFactory loggerFactory, IEnumerable additionalTargetAssemblies = null) { _entryPointAssembly = entryPointAssembly ?? throw new ArgumentNullException(nameof(entryPointAssembly)); _loggerFactory = loggerFactory; _additionalTargetAssemblies = additionalTargetAssemblies; } // TODO: It would be worth investigating a netcore3 version of this which would use // var allAssemblies = System.Runtime.Loader.AssemblyLoadContext.All.SelectMany(x => x.Assemblies); // that will still only resolve Assemblies that are already loaded but it would also make it possible to // query dynamically generated assemblies once they are added. It would also provide the ability to probe // assembly locations that are not in the same place as the entry point assemblies. public IEnumerable Assemblies { get { if (_discovered != null) { return _discovered; } IEnumerable additionalTargetAssemblies = Constants.Composing.UmbracoCoreAssemblyNames; if (_additionalTargetAssemblies != null) { additionalTargetAssemblies = additionalTargetAssemblies.Concat(_additionalTargetAssemblies); } var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, additionalTargetAssemblies.ToArray(), true, _loggerFactory); _discovered = finder.Find().ToList(); return _discovered; } } } }