diff --git a/src/Umbraco.Core/TypeFinder.cs b/src/Umbraco.Core/TypeFinder.cs
index 6b7627e257..2630133a62 100644
--- a/src/Umbraco.Core/TypeFinder.cs
+++ b/src/Umbraco.Core/TypeFinder.cs
@@ -2,23 +2,18 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Linq.Expressions;
using System.Reflection;
using System.Security;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Compilation;
-using System.Web.Hosting;
-using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
namespace Umbraco.Core
{
-
//TODO: Get the App_Code stuff in here from the old one
///
@@ -27,7 +22,6 @@ namespace Umbraco.Core
///
public static class TypeFinder
{
-
private static readonly ConcurrentBag LocalFilteredAssemblyCache = new ConcurrentBag();
private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim();
private static ReadOnlyCollection _allAssemblies = null;
@@ -86,8 +80,7 @@ namespace Umbraco.Core
}
//now set the _allAssemblies
- _allAssemblies = new ReadOnlyCollection(assemblies);
-
+ _allAssemblies = new ReadOnlyCollection(assemblies);
}
catch (InvalidOperationException e)
{
@@ -100,8 +93,8 @@ namespace Umbraco.Core
}
return _allAssemblies;
- }
-
+ }
+
///
/// Returns only assemblies found in the bin folder that have been loaded into the app domain.
///
@@ -111,7 +104,6 @@ namespace Umbraco.Core
///
internal static IEnumerable GetBinAssemblies()
{
-
if (_binFolderAssemblies == null)
{
using (new WriteLock(Locker))
@@ -143,7 +135,8 @@ namespace Umbraco.Core
{
try
{
- var foundAssembly = safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile());
+ var foundAssembly =
+ safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile());
if (foundAssembly != null)
{
binFolderAssemblies.Add(foundAssembly);
@@ -162,7 +155,7 @@ namespace Umbraco.Core
}
}
return _binFolderAssemblies;
- }
+ }
///
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
@@ -181,7 +174,7 @@ namespace Umbraco.Core
assemblies.ForEach(LocalFilteredAssemblyCache.Add);
}
return LocalFilteredAssemblyCache;
- }
+ }
///
/// Return a list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter
@@ -190,18 +183,18 @@ namespace Umbraco.Core
///
///
private static IEnumerable GetFilteredAssemblies(
- IEnumerable excludeFromResults = null,
+ IEnumerable excludeFromResults = null,
string[] exclusionFilter = null)
{
if (excludeFromResults == null)
excludeFromResults = new List();
if (exclusionFilter == null)
- exclusionFilter = new string[] { };
+ exclusionFilter = new string[] {};
return GetAllAssemblies()
.Where(x => !excludeFromResults.Contains(x)
- && !x.GlobalAssemblyCache
- && !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
+ && !x.GlobalAssemblyCache
+ && !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
}
///
@@ -211,42 +204,42 @@ namespace Umbraco.Core
/// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match
///
internal static readonly string[] KnownAssemblyExclusionFilter = new[]
- {
- "mscorlib,",
- "System.",
- "Antlr3.",
- "Autofac.",
- "Autofac,",
- "Castle.",
- "ClientDependency.",
- "DataAnnotationsExtensions.",
- "DataAnnotationsExtensions,",
- "Dynamic,",
- "HtmlDiff,",
- "Iesi.Collections,",
- "log4net,",
- "Microsoft.",
- "Newtonsoft.",
- "NHibernate.",
- "NHibernate,",
- "NuGet.",
- "RouteDebugger,",
- "SqlCE4Umbraco,",
- "umbraco.datalayer,",
- "umbraco.interfaces,",
- "umbraco.providers,",
- "Umbraco.Web.UI,",
- "umbraco.webservices",
- "Lucene.",
- "Examine,",
- "Examine.",
- "ServiceStack.",
- "MySql.",
- "HtmlAgilityPack.",
- "TidyNet.",
- "ICSharpCode.",
- "CookComputing."
- };
+ {
+ "mscorlib,",
+ "System.",
+ "Antlr3.",
+ "Autofac.",
+ "Autofac,",
+ "Castle.",
+ "ClientDependency.",
+ "DataAnnotationsExtensions.",
+ "DataAnnotationsExtensions,",
+ "Dynamic,",
+ "HtmlDiff,",
+ "Iesi.Collections,",
+ "log4net,",
+ "Microsoft.",
+ "Newtonsoft.",
+ "NHibernate.",
+ "NHibernate,",
+ "NuGet.",
+ "RouteDebugger,",
+ "SqlCE4Umbraco,",
+ "umbraco.datalayer,",
+ "umbraco.interfaces,",
+ "umbraco.providers,",
+ "Umbraco.Web.UI,",
+ "umbraco.webservices",
+ "Lucene.",
+ "Examine,",
+ "Examine.",
+ "ServiceStack.",
+ "MySql.",
+ "HtmlAgilityPack.",
+ "TidyNet.",
+ "ICSharpCode.",
+ "CookComputing."
+ };
public static IEnumerable FindClassesOfTypeWithAttribute()
where TAttribute : Attribute
@@ -260,13 +253,19 @@ namespace Umbraco.Core
return FindClassesOfTypeWithAttribute(assemblies, true);
}
- public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses)
+ public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies,
+ bool onlyConcreteClasses)
where TAttribute : Attribute
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
+ // a assembly cant contain types that are assignable to a type it doesn't reference
+ assemblies = RemoveAssembliesThatDontReferenceAssemblyOfType(typeof (T), assemblies);
+ // a assembly cant contain types with a attribute it doesn't reference
+ assemblies = RemoveAssembliesThatDontReferenceAssemblyOfType(typeof (TAttribute), assemblies);
+
var l = new List();
- foreach(var a in assemblies)
+ foreach (var a in assemblies)
{
var types = from t in GetTypesWithFormattedException(a)
where !t.IsInterface
@@ -325,7 +324,7 @@ namespace Umbraco.Core
public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses)
where T : Attribute
{
- return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses);
+ return FindClassesWithAttribute(typeof (T), assemblies, onlyConcreteClasses);
}
///
@@ -335,23 +334,58 @@ namespace Umbraco.Core
/// The assemblies.
/// if set to true only concrete classes.
///
- public static IEnumerable FindClassesWithAttribute(Type type, IEnumerable assemblies, bool onlyConcreteClasses)
+ public static IEnumerable FindClassesWithAttribute(Type type, IEnumerable assemblies,
+ bool onlyConcreteClasses)
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
if (!TypeHelper.IsTypeAssignableFrom(type))
throw new ArgumentException("The type specified: " + type + " is not an Attribute type");
+ // a assembly cant contain types with a attribute it doesn't reference
+ assemblies = RemoveAssembliesThatDontReferenceAssemblyOfType(type, assemblies);
var l = new List();
foreach (var a in assemblies)
{
var types = from t in GetTypesWithFormattedException(a)
- where !t.IsInterface && t.GetCustomAttributes(type, false).Any() && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
- select t;
+ where
+ !t.IsInterface && t.GetCustomAttributes(type, false).Any() &&
+ (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
+ select t;
l.AddRange(types);
}
return l;
}
+ ///
+ /// Removes assemblies that doesn't reference the assembly of the type we are looking for.
+ ///
+ ///
+ ///
+ ///
+ private static IEnumerable RemoveAssembliesThatDontReferenceAssemblyOfType(Type type,
+ IEnumerable assemblies)
+ {
+ // Avoid scanning assembly if it doesn't contain a reference to the assembly containing the type we are looking for
+ // to the assembly containing the attribute we are looking for
+ var assemblyNameOfType = type.Assembly.GetName().Name;
+
+ return assemblies
+ .Where(assembly => assembly == type.Assembly
+ || HasReferenceToAssemblyWithName(assembly, assemblyNameOfType)).ToList();
+ }
+ ///
+ /// checks if the assembly has a reference with the same name as the expected assembly name.
+ ///
+ ///
+ ///
+ ///
+ private static bool HasReferenceToAssemblyWithName(Assembly assembly, string expectedAssemblyName)
+ {
+ return assembly
+ .GetReferencedAssemblies()
+ .Select(a => a.Name)
+ .Contains(expectedAssemblyName, StringComparer.Ordinal);
+ }
///
/// Finds the classes with attribute.
@@ -376,9 +410,8 @@ namespace Umbraco.Core
return FindClassesWithAttribute(GetAssembliesWithKnownExclusions());
}
-
#region Private methods
-
+
///
/// Gets a collection of assignables of type T from a collection of assemblies
///
@@ -388,20 +421,26 @@ namespace Umbraco.Core
///
private static IEnumerable GetAssignablesFromType(IEnumerable assemblies, bool onlyConcreteClasses)
{
- return GetTypes(typeof(T), assemblies, onlyConcreteClasses);
+ return GetTypes(typeof (T), assemblies, onlyConcreteClasses);
}
- private static IEnumerable GetTypes(Type assignTypeFrom, IEnumerable assemblies, bool onlyConcreteClasses)
+ private static IEnumerable GetTypes(Type assignTypeFrom, IEnumerable assemblies,
+ bool onlyConcreteClasses)
{
+ // a assembly cant contain types that are assignable to a type it doesn't reference
+ assemblies = RemoveAssembliesThatDontReferenceAssemblyOfType(assignTypeFrom, assemblies);
+
var l = new List();
foreach (var a in assemblies)
{
var types = from t in GetTypesWithFormattedException(a)
- where !t.IsInterface && assignTypeFrom.IsAssignableFrom(t) && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
+ where
+ !t.IsInterface && assignTypeFrom.IsAssignableFrom(t) &&
+ (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
select t;
l.AddRange(types);
}
- return l;
+ return l;
}
private static IEnumerable GetTypesWithFormattedException(Assembly a)
@@ -420,15 +459,12 @@ namespace Umbraco.Core
sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:");
foreach (var loaderException in ex.LoaderExceptions.WhereNotNull())
{
- sb.AppendLine("Exception: " + loaderException.ToString());
+ sb.AppendLine("Exception: " + loaderException);
}
throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
}
}
#endregion
-
-
-
}
-}
+}
\ No newline at end of file