Ensures all assemblies at the same location as the entry point assemblies are queried.

This commit is contained in:
Shannon
2020-03-09 14:15:02 +11:00
parent d92fc8736a
commit fce27fd42d
2 changed files with 66 additions and 7 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -15,27 +16,63 @@ namespace Umbraco.Core.Composing
internal class ReferenceResolver
{
private readonly HashSet<string> _umbracoAssemblies;
private readonly IReadOnlyList<Assembly> _assemblyItems;
private readonly IReadOnlyList<Assembly> _assemblies;
private readonly Dictionary<Assembly, Classification> _classifications;
private readonly List<Assembly> _lookup = new List<Assembly>();
public ReferenceResolver(IReadOnlyList<string> targetAssemblies, IReadOnlyList<Assembly> assemblyItems)
public ReferenceResolver(IReadOnlyList<string> targetAssemblies, IReadOnlyList<Assembly> entryPointAssemblies)
{
_umbracoAssemblies = new HashSet<string>(targetAssemblies, StringComparer.Ordinal);
_assemblyItems = assemblyItems;
_assemblies = entryPointAssemblies;
_classifications = new Dictionary<Assembly, Classification>();
foreach (var item in assemblyItems)
foreach (var item in entryPointAssemblies)
{
_lookup.Add(item);
}
}
/// <summary>
/// Returns a list of assemblies that directly reference or transitively reference the targetAssemblies
/// </summary>
/// <returns></returns>
/// <remarks>
/// This includes all assemblies in the same location as the entry point assemblies
/// </remarks>
public IEnumerable<Assembly> ResolveAssemblies()
{
var applicationParts = new List<Assembly>();
foreach (var item in _assemblyItems)
var assemblies = new HashSet<Assembly>(_assemblies);
// Get the unique directories of the assemblies
var assemblyLocations = GetAssemblyLocations(assemblies).ToList();
// Load in each assembly in the directory of the entry assembly to be included in the search
// for Umbraco dependencies/transitive dependencies
foreach(var location in assemblyLocations)
{
var dir = Path.GetDirectoryName(location);
foreach(var dll in Directory.EnumerateFiles(dir, "*.dll"))
{
var assemblyName = AssemblyName.GetAssemblyName(dll);
// don't include if this is excluded
if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => assemblyName.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
continue;
// don't include this item if it's Umbraco
// TODO: We should maybe pass an explicit list of these names in?
if (assemblyName.FullName.StartsWith("Umbraco."))
continue;
var assembly = Assembly.Load(assemblyName);
assemblies.Add(assembly);
}
}
foreach (var item in assemblies)
{
var classification = Resolve(item);
if (classification == Classification.ReferencesUmbraco || classification == Classification.IsUmbraco)
@@ -47,6 +84,24 @@ namespace Umbraco.Core.Composing
return applicationParts;
}
private IEnumerable<string> GetAssemblyLocations(IEnumerable<Assembly> assemblies)
{
return assemblies.Select(x => GetAssemblyLocation(x).ToLowerInvariant()).Distinct();
}
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/ApplicationParts/RelatedAssemblyAttribute.cs
private string GetAssemblyLocation(Assembly assembly)
{
if (Uri.TryCreate(assembly.CodeBase, UriKind.Absolute, out var result) &&
result.IsFile && string.IsNullOrWhiteSpace(result.Fragment))
{
return result.LocalPath;
}
return assembly.Location;
}
private Classification Resolve(Assembly assemblyItem)
{
if (_classifications.TryGetValue(assemblyItem, out var classification))
@@ -88,7 +143,7 @@ namespace Umbraco.Core.Composing
foreach (var referenceName in assembly.GetReferencedAssemblies())
{
// don't include if this is excluded
if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => referenceName.FullName.StartsWith(f)))
if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => referenceName.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
continue;
var reference = Assembly.Load(referenceName);

View File

@@ -142,8 +142,12 @@ namespace Umbraco.Core.Composing
"itextsharp,",
"mscorlib,",
"NUnit,",
"NUnit3TestAdapter,",
"NUnit.",
"NUnit3.",
"Selenium.",
"ImageProcessor",
"MiniProfiler.",
"Owin,",
};
/// <summary>