diff --git a/src/Umbraco.Core/TypeFinder.cs b/src/Umbraco.Core/TypeFinder.cs
index 3cbe21991b..36a5deff75 100644
--- a/src/Umbraco.Core/TypeFinder.cs
+++ b/src/Umbraco.Core/TypeFinder.cs
@@ -19,54 +19,56 @@ using Umbraco.Core.IO;
namespace Umbraco.Core
{
- ///
- /// A utility class to find all classes of a certain type by reflection in the current bin folder
- /// of the web application.
- ///
- public static class TypeFinder
- {
-
- private static readonly ConcurrentBag LocalFilteredAssemblyCache = new ConcurrentBag();
- private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim();
- private static ReadOnlyCollection _allAssemblies = null;
- private static ReadOnlyCollection _binFolderAssemblies = null;
- private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
+ ///
+ /// A utility class to find all classes of a certain type by reflection in the current bin folder
+ /// of the web application.
+ ///
+ public static class TypeFinder
+ {
+ private static readonly HashSet LocalFilteredAssemblyCache = new HashSet();
+ private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim();
+ private static HashSet _allAssemblies = null;
+ private static HashSet _binFolderAssemblies = null;
+ private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
- ///
- /// lazily load a reference to all assemblies and only local 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
- ///
- internal static IEnumerable GetAllAssemblies()
- {
- if (_allAssemblies == null)
- {
- using (new WriteLock(Locker))
- {
- List assemblies = null;
- try
- {
- var isHosted = HttpContext.Current != null;
+ ///
+ /// lazily load a reference to all assemblies and only local 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
+ ///
+ internal static HashSet GetAllAssemblies()
+ {
+ using (var lck = new UpgradeableReadLock(Locker))
+ {
+ if (_allAssemblies == null)
+ {
- try
- {
- if (isHosted)
- {
- assemblies = new List(BuildManager.GetReferencedAssemblies().Cast());
- }
- }
- catch (InvalidOperationException e)
- {
- if (!(e.InnerException is SecurityException))
- throw;
- }
+ lck.UpgradeToWriteLock();
+
+ HashSet assemblies = null;
+ try
+ {
+ var isHosted = HttpContext.Current != null;
+
+ try
+ {
+ if (isHosted)
+ {
+ assemblies = new HashSet(BuildManager.GetReferencedAssemblies().Cast());
+ }
+ }
+ catch (InvalidOperationException e)
+ {
+ if (!(e.InnerException is SecurityException))
+ throw;
+ }
if (assemblies == null)
@@ -77,7 +79,7 @@ namespace Umbraco.Core
var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
//var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
//var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
- assemblies = new List();
+ assemblies = new HashSet();
foreach (var a in binAssemblyFiles)
{
try
@@ -99,151 +101,161 @@ namespace Umbraco.Core
}
}
}
-
+
//if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies.
- if (!assemblies.Any())
- {
- assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList());
- }
+ if (!assemblies.Any())
+ {
+ foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ assemblies.Add(a);
+ }
+ }
- //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())))
- {
- var appCodeAssembly = Assembly.Load("App_Code");
- if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already
- assemblies.Add(appCodeAssembly);
- }
+ //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())))
+ {
+ var appCodeAssembly = Assembly.Load("App_Code");
+ if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already
+ assemblies.Add(appCodeAssembly);
+ }
- //now set the _allAssemblies
- _allAssemblies = new ReadOnlyCollection(assemblies);
+ //now set the _allAssemblies
+ _allAssemblies = new HashSet(assemblies);
- }
- catch (InvalidOperationException e)
- {
- if (!(e.InnerException is SecurityException))
- throw;
+ }
+ catch (InvalidOperationException e)
+ {
+ if (!(e.InnerException is SecurityException))
+ throw;
- _binFolderAssemblies = _allAssemblies;
- }
- }
- }
+ _binFolderAssemblies = _allAssemblies;
+ }
+ }
- return _allAssemblies;
- }
-
- ///
- /// Returns only assemblies found in the bin folder that have been loaded into the app domain.
- ///
- ///
- ///
- /// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used.
- ///
- internal static IEnumerable GetBinAssemblies()
- {
+ return _allAssemblies;
+ }
+ }
- if (_binFolderAssemblies == null)
- {
- using (new WriteLock(Locker))
- {
- var assemblies = GetAssembliesWithKnownExclusions().ToArray();
- var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
- var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
- var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName);
- var safeDomainAssemblies = new List();
- var binFolderAssemblies = new List();
+ ///
+ /// Returns only assemblies found in the bin folder that have been loaded into the app domain.
+ ///
+ ///
+ ///
+ /// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used.
+ ///
+ internal static HashSet GetBinAssemblies()
+ {
- foreach (var a in assemblies)
- {
- try
- {
- //do a test to see if its queryable in med trust
- var assemblyFile = a.GetAssemblyFile();
- safeDomainAssemblies.Add(a);
- }
- catch (SecurityException)
- {
- //we will just ignore this because this will fail
- //in medium trust for system assemblies, we get an exception but we just want to continue until we get to
- //an assembly that is ok.
- }
- }
+ if (_binFolderAssemblies == null)
+ {
+ using (new WriteLock(Locker))
+ {
+ var assemblies = GetAssembliesWithKnownExclusions().ToArray();
+ var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
+ var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
+ var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName);
+ var safeDomainAssemblies = new HashSet();
+ var binFolderAssemblies = new HashSet();
- foreach (var assemblyName in domainAssemblyNames)
- {
- try
- {
- var foundAssembly =
- safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile());
- if (foundAssembly != null)
- {
- binFolderAssemblies.Add(foundAssembly);
- }
- }
- catch (SecurityException)
- {
- //we will just ignore this because if we are trying to do a call to:
- // AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName)))
- //in medium trust for system assemblies, we get an exception but we just want to continue until we get to
- //an assembly that is ok.
- }
- }
+ foreach (var a in assemblies)
+ {
+ try
+ {
+ //do a test to see if its queryable in med trust
+ var assemblyFile = a.GetAssemblyFile();
+ safeDomainAssemblies.Add(a);
+ }
+ catch (SecurityException)
+ {
+ //we will just ignore this because this will fail
+ //in medium trust for system assemblies, we get an exception but we just want to continue until we get to
+ //an assembly that is ok.
+ }
+ }
- _binFolderAssemblies = new ReadOnlyCollection(binFolderAssemblies);
- }
- }
- return _binFolderAssemblies;
- }
+ foreach (var assemblyName in domainAssemblyNames)
+ {
+ try
+ {
+ var foundAssembly =
+ safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile());
+ if (foundAssembly != null)
+ {
+ binFolderAssemblies.Add(foundAssembly);
+ }
+ }
+ catch (SecurityException)
+ {
+ //we will just ignore this because if we are trying to do a call to:
+ // AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName)))
+ //in medium trust for system assemblies, we get an exception but we just want to continue until we get to
+ //an assembly that is ok.
+ }
+ }
- ///
- /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
- /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
- /// cached for perforance reasons.
- ///
- ///
- ///
- internal static IEnumerable GetAssembliesWithKnownExclusions(
- IEnumerable excludeFromResults = null)
- {
- if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache;
- using (new WriteLock(LocalFilteredAssemblyCacheLocker))
- {
- var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
- assemblies.ForEach(LocalFilteredAssemblyCache.Add);
- }
- return LocalFilteredAssemblyCache;
- }
+ _binFolderAssemblies = new HashSet(binFolderAssemblies);
+ }
+ }
+ return _binFolderAssemblies;
+ }
- ///
- /// Return a list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter
- ///
- ///
- ///
- ///
- private static IEnumerable GetFilteredAssemblies(
- IEnumerable excludeFromResults = null,
- string[] exclusionFilter = null)
- {
- if (excludeFromResults == null)
- excludeFromResults = new List();
- if (exclusionFilter == null)
- exclusionFilter = new string[] { };
+ ///
+ /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
+ /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
+ /// cached for perforance reasons.
+ ///
+ ///
+ ///
+ internal static HashSet GetAssembliesWithKnownExclusions(
+ IEnumerable excludeFromResults = null)
+ {
+ using (var lck = new UpgradeableReadLock(LocalFilteredAssemblyCacheLocker))
+ {
+ if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache;
- return GetAllAssemblies()
- .Where(x => !excludeFromResults.Contains(x)
- && !x.GlobalAssemblyCache
- && !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
- }
+ lck.UpgradeToWriteLock();
- ///
- /// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins
- ///
- ///
- /// 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[]
+ var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
+ foreach (var a in assemblies)
+ {
+ LocalFilteredAssemblyCache.Add(a);
+ }
+
+ return LocalFilteredAssemblyCache;
+ }
+ }
+
+ ///
+ /// Return a distinct list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter
+ ///
+ ///
+ ///
+ ///
+ private static IEnumerable GetFilteredAssemblies(
+ IEnumerable excludeFromResults = null,
+ string[] exclusionFilter = null)
+ {
+ if (excludeFromResults == null)
+ excludeFromResults = new HashSet();
+ if (exclusionFilter == null)
+ exclusionFilter = new string[] { };
+
+ return GetAllAssemblies()
+ .Where(x => !excludeFromResults.Contains(x)
+ && !x.GlobalAssemblyCache
+ && !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
+ }
+
+ ///
+ /// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins
+ ///
+ ///
+ /// 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.",
@@ -287,11 +299,11 @@ namespace Umbraco.Core
///
///
///
- public static IEnumerable FindClassesOfTypeWithAttribute()
- where TAttribute : Attribute
- {
- return FindClassesOfTypeWithAttribute(GetAssembliesWithKnownExclusions(), true);
- }
+ public static IEnumerable FindClassesOfTypeWithAttribute()
+ where TAttribute : Attribute
+ {
+ return FindClassesOfTypeWithAttribute(GetAssembliesWithKnownExclusions(), true);
+ }
///
/// Finds any classes derived from the type T that contain the attribute TAttribute
@@ -300,11 +312,11 @@ namespace Umbraco.Core
///
///
///
- public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies)
- where TAttribute : Attribute
- {
- return FindClassesOfTypeWithAttribute(assemblies, true);
- }
+ public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies)
+ where TAttribute : Attribute
+ {
+ return FindClassesOfTypeWithAttribute(assemblies, true);
+ }
///
/// Finds any classes derived from the type T that contain the attribute TAttribute
@@ -314,13 +326,13 @@ namespace Umbraco.Core
///
///
///
- public static IEnumerable FindClassesOfTypeWithAttribute(
- IEnumerable assemblies,
- bool onlyConcreteClasses)
- where TAttribute : Attribute
- {
- return FindClassesOfTypeWithAttribute(typeof (T), assemblies, onlyConcreteClasses);
- }
+ public static IEnumerable FindClassesOfTypeWithAttribute(
+ IEnumerable assemblies,
+ bool onlyConcreteClasses)
+ where TAttribute : Attribute
+ {
+ return FindClassesOfTypeWithAttribute(typeof(T), assemblies, onlyConcreteClasses);
+ }
///
/// Finds any classes derived from the assignTypeFrom Type that contain the attribute TAttribute
@@ -330,85 +342,85 @@ namespace Umbraco.Core
///
///
///
- public static IEnumerable FindClassesOfTypeWithAttribute(
- Type assignTypeFrom,
- IEnumerable assemblies,
+ public static IEnumerable FindClassesOfTypeWithAttribute(
+ Type assignTypeFrom,
+ IEnumerable assemblies,
bool onlyConcreteClasses)
where TAttribute : Attribute
- {
- if (assemblies == null) throw new ArgumentNullException("assemblies");
-
- return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses,
+ {
+ if (assemblies == null) throw new ArgumentNullException("assemblies");
+
+ return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses,
//the additional filter will ensure that any found types also have the attribute applied.
- t => t.GetCustomAttributes(false).Any());
- }
+ t => t.GetCustomAttributes(false).Any());
+ }
- ///
- /// Searches all filtered local assemblies specified for classes of the type passed in.
- ///
- ///
- ///
- public static IEnumerable FindClassesOfType()
- {
- return FindClassesOfType(GetAssembliesWithKnownExclusions(), true);
- }
+ ///
+ /// Searches all filtered local assemblies specified for classes of the type passed in.
+ ///
+ ///
+ ///
+ public static IEnumerable FindClassesOfType()
+ {
+ return FindClassesOfType(GetAssembliesWithKnownExclusions(), true);
+ }
- ///
- /// Returns all types found of in the assemblies specified of type T
- ///
- ///
- ///
- ///
- ///
- public static IEnumerable FindClassesOfType(IEnumerable assemblies, bool onlyConcreteClasses)
- {
- if (assemblies == null) throw new ArgumentNullException("assemblies");
+ ///
+ /// Returns all types found of in the assemblies specified of type T
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IEnumerable FindClassesOfType(IEnumerable assemblies, bool onlyConcreteClasses)
+ {
+ if (assemblies == null) throw new ArgumentNullException("assemblies");
return GetClasses(typeof(T), assemblies, onlyConcreteClasses);
- }
+ }
- ///
- /// Returns all types found of in the assemblies specified of type T
- ///
- ///
- ///
- ///
- public static IEnumerable FindClassesOfType(IEnumerable assemblies)
- {
- return FindClassesOfType(assemblies, true);
- }
+ ///
+ /// Returns all types found of in the assemblies specified of type T
+ ///
+ ///
+ ///
+ ///
+ public static IEnumerable FindClassesOfType(IEnumerable assemblies)
+ {
+ return FindClassesOfType(assemblies, true);
+ }
- ///
- /// Finds the classes with attribute.
- ///
- ///
- /// The assemblies.
- /// if set to true only concrete classes.
- ///
- public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses)
- where T : Attribute
- {
- return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses);
- }
+ ///
+ /// Finds the classes with attribute.
+ ///
+ ///
+ /// The assemblies.
+ /// if set to true only concrete classes.
+ ///
+ public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses)
+ where T : Attribute
+ {
+ return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses);
+ }
- ///
- /// Finds any classes with the attribute.
- ///
- /// The attribute type
- /// The assemblies.
- /// if set to true only concrete classes.
- ///
- public static IEnumerable FindClassesWithAttribute(
- Type attributeType,
- IEnumerable assemblies,
- bool onlyConcreteClasses)
- {
- if (assemblies == null) throw new ArgumentNullException("assemblies");
+ ///
+ /// Finds any classes with the attribute.
+ ///
+ /// The attribute type
+ /// The assemblies.
+ /// if set to true only concrete classes.
+ ///
+ public static IEnumerable FindClassesWithAttribute(
+ Type attributeType,
+ IEnumerable assemblies,
+ bool onlyConcreteClasses)
+ {
+ if (assemblies == null) throw new ArgumentNullException("assemblies");
- if (TypeHelper.IsTypeAssignableFrom(attributeType) == false)
- throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type");
+ if (TypeHelper.IsTypeAssignableFrom(attributeType) == false)
+ throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type");
- var foundAssignableTypes = new List();
+ var foundAssignableTypes = new HashSet();
var assemblyList = assemblies.ToArray();
@@ -418,71 +430,74 @@ namespace Umbraco.Core
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(attributeType, assemblyList);
foreach (var a in referencedAssemblies)
- {
+ {
//get all types in the assembly that are sub types of the current type
var allTypes = GetTypesWithFormattedException(a).ToArray();
-
- var types = allTypes.Where(t => TypeHelper.IsNonStaticClass(t)
- && (onlyConcreteClasses == false || t.IsAbstract == false)
- //the type must have this attribute
+
+ var types = allTypes.Where(t => TypeHelper.IsNonStaticClass(t)
+ && (onlyConcreteClasses == false || t.IsAbstract == false)
+ //the type must have this attribute
&& t.GetCustomAttributes(attributeType, false).Any());
- foundAssignableTypes.AddRange(types);
- }
+ foreach (var t in types)
+ {
+ foundAssignableTypes.Add(t);
+ }
+ }
- return foundAssignableTypes;
- }
+ return foundAssignableTypes;
+ }
- ///
- /// Finds the classes with attribute.
- ///
- ///
- /// The assemblies.
- ///
- public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies)
- where T : Attribute
- {
- return FindClassesWithAttribute(assemblies, true);
- }
+ ///
+ /// Finds the classes with attribute.
+ ///
+ ///
+ /// The assemblies.
+ ///
+ public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies)
+ where T : Attribute
+ {
+ return FindClassesWithAttribute(assemblies, true);
+ }
- ///
- /// Finds the classes with attribute in filtered local assemblies
- ///
- ///
- ///
- public static IEnumerable FindClassesWithAttribute()
- where T : Attribute
- {
- return FindClassesWithAttribute(GetAssembliesWithKnownExclusions());
- }
+ ///
+ /// Finds the classes with attribute in filtered local assemblies
+ ///
+ ///
+ ///
+ public static IEnumerable FindClassesWithAttribute()
+ where T : Attribute
+ {
+ return FindClassesWithAttribute(GetAssembliesWithKnownExclusions());
+ }
- #region Private methods
-
- ///
- /// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
- /// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
- /// deriving from the base type.
- ///
- ///
- ///
- ///
- /// An additional filter to apply for what types will actually be included in the return value
- ///
- private static IEnumerable GetClasses(
- Type assignTypeFrom,
- IEnumerable assemblies,
+ #region Private methods
+
+ ///
+ /// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
+ /// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
+ /// deriving from the base type.
+ ///
+ ///
+ ///
+ ///
+ /// An additional filter to apply for what types will actually be included in the return value
+ ///
+ private static IEnumerable GetClasses(
+ Type assignTypeFrom,
+ IEnumerable assemblies,
bool onlyConcreteClasses,
Func additionalFilter = null)
- {
+ {
//the default filter will always return true.
if (additionalFilter == null)
{
additionalFilter = type => true;
}
- var foundAssignableTypes = new List();
+ var foundAssignableTypes = new HashSet();
var assemblyList = assemblies.ToArray();
@@ -510,8 +525,11 @@ namespace Umbraco.Core
.ToArray();
//add the types to our list to return
- foundAssignableTypes.AddRange(filteredTypes);
-
+ foreach (var t in filteredTypes)
+ {
+ foundAssignableTypes.Add(t);
+ }
+
//now we need to include types that may be inheriting from sub classes of the type being searched for
//so we will search in assemblies that reference those types too.
foreach (var subTypesInAssembly in allSubTypes.GroupBy(x => x.Assembly))
@@ -529,54 +547,61 @@ namespace Umbraco.Core
//if there's a base class amongst the types then we'll only search for that type.
//otherwise we'll have to search for all of them.
- var subTypesToSearch = new List();
+ var subTypesToSearch = new HashSet();
if (baseClassAttempt.Success)
{
subTypesToSearch.Add(baseClassAttempt.Result);
}
else
{
- subTypesToSearch.AddRange(subTypeList);
+ foreach (var t in subTypeList)
+ {
+ subTypesToSearch.Add(t);
+ }
}
-
+
foreach (var typeToSearch in subTypesToSearch)
{
//recursively find the types inheriting from this sub type in the other non-scanned assemblies.
var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses, additionalFilter);
- foundAssignableTypes.AddRange(foundTypes);
+
+ foreach (var f in foundTypes)
+ {
+ foundAssignableTypes.Add(f);
+ }
}
-
+
}
- }
- return foundAssignableTypes;
- }
+ }
+ return foundAssignableTypes;
+ }
- private static IEnumerable GetTypesWithFormattedException(Assembly a)
- {
- //if the assembly is dynamic, do not try to scan it
- if (a.IsDynamic)
- return Enumerable.Empty();
+ private static IEnumerable GetTypesWithFormattedException(Assembly a)
+ {
+ //if the assembly is dynamic, do not try to scan it
+ if (a.IsDynamic)
+ return Enumerable.Empty();
- try
- {
- return a.GetExportedTypes();
- }
- catch (ReflectionTypeLoadException ex)
- {
- var sb = new StringBuilder();
- sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:");
- foreach (var loaderException in ex.LoaderExceptions.WhereNotNull())
- {
- sb.AppendLine("Exception: " + loaderException);
- }
- throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
- }
- }
+ try
+ {
+ return a.GetExportedTypes();
+ }
+ catch (ReflectionTypeLoadException ex)
+ {
+ var sb = new StringBuilder();
+ sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:");
+ foreach (var loaderException in ex.LoaderExceptions.WhereNotNull())
+ {
+ sb.AppendLine("Exception: " + loaderException);
+ }
+ throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
+ }
+ }
- #endregion
+ #endregion
-
- }
+
+ }
}