diff --git a/src/Umbraco.Core/AssemblyExtensions.cs b/src/Umbraco.Core/AssemblyExtensions.cs
index 666dce18fc..fff444c34a 100644
--- a/src/Umbraco.Core/AssemblyExtensions.cs
+++ b/src/Umbraco.Core/AssemblyExtensions.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Reflection;
namespace Umbraco.Core
@@ -66,5 +68,31 @@ namespace Umbraco.Core
return new FileInfo(path);
}
+ ///
+ /// Gets the objects for all the assemblies recursively referenced by a specified assembly.
+ ///
+ /// The assembly.
+ /// The objects for all the assemblies recursively referenced by the specified assembly.
+ public static IEnumerable GetDeepReferencedAssemblies(this Assembly assembly)
+ {
+ var allAssemblies = TypeFinder.GetAllAssemblies();
+ var visiting = new Stack();
+ var visited = new HashSet();
+
+ visiting.Push(assembly);
+ visited.Add(assembly);
+ while (visiting.Count > 0)
+ {
+ var visAsm = visiting.Pop();
+ foreach (var refAsm in visAsm.GetReferencedAssemblies()
+ .Select(refAsmName => allAssemblies.SingleOrDefault(x => string.Equals(x.GetName().Name, refAsmName.Name, StringComparison.Ordinal)))
+ .Where(x => x != null && visited.Contains(x) == false))
+ {
+ yield return refAsm.GetName();
+ visiting.Push(refAsm);
+ visited.Add(refAsm);
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/TypeHelper.cs b/src/Umbraco.Core/TypeHelper.cs
index efb525e575..5cb82b3863 100644
--- a/src/Umbraco.Core/TypeHelper.cs
+++ b/src/Umbraco.Core/TypeHelper.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@@ -62,8 +63,17 @@ namespace Umbraco.Core
///
private static bool HasReferenceToAssemblyWithName(Assembly assembly, string expectedAssemblyName)
{
+ // The following code was not recursive ie if assembly.1 -> assembly.2 -> assembly.3, and expected is assembly.3,
+ // it would not consider that assembly.1 has a reference to assembly.3. Can cause issues eg when assembly.3
+ // contains an attribute, assembly.2 defines a new attribute that inherit from that attribute, and assembly.1
+ // uses the attribute in assembly.2. When looking for assemblies that have a chance to use the attribute, we
+ // look for assemblies that reference assembly.3, and we would fail to consider assembly.1.
+ //
+ // Better get deep-referenced assemblies. Has an impact on perfs obviously but only when the app starts.
+
return assembly
- .GetReferencedAssemblies()
+ //.GetReferencedAssemblies()
+ .GetDeepReferencedAssemblies()
.Select(a => a.Name)
.Contains(expectedAssemblyName, StringComparer.Ordinal);
}