diff --git a/src/Umbraco.Core/PluginTypeResolver.cs b/src/Umbraco.Core/PluginTypeResolver.cs index 426029de61..d2e373fdd5 100644 --- a/src/Umbraco.Core/PluginTypeResolver.cs +++ b/src/Umbraco.Core/PluginTypeResolver.cs @@ -73,14 +73,9 @@ namespace Umbraco.Core } } return instances; - } + } - /// - /// Generic method to find the specified type and cache the result - /// - /// - /// - internal IEnumerable ResolveTypes() + private IEnumerable ResolveTypes(Func> finder) { using (var readLock = new UpgradeableReadLock(_lock)) { @@ -93,7 +88,7 @@ namespace Umbraco.Core typeList = new TypeList(); - foreach (var t in TypeFinder.FindClassesOfType()) + foreach (var t in finder()) { typeList.AddType(t); } @@ -103,8 +98,28 @@ namespace Umbraco.Core } return typeList.GetTypes(); } + } + /// + /// Generic method to find the specified type and cache the result + /// + /// + /// + internal IEnumerable ResolveTypes() + { + return ResolveTypes(() => TypeFinder.FindClassesOfType()); + } + /// + /// Generic method to find the specified type that has an attribute and cache the result + /// + /// + /// + /// + internal IEnumerable ResolveTypesWithAttribute() + where TAttribute : Attribute + { + return ResolveTypes(() => TypeFinder.FindClassesOfTypeWithAttribute()); } /// diff --git a/src/Umbraco.Core/TypeFinder2.cs b/src/Umbraco.Core/TypeFinder2.cs index 8f9f67b4bc..d5641be4a5 100644 --- a/src/Umbraco.Core/TypeFinder2.cs +++ b/src/Umbraco.Core/TypeFinder2.cs @@ -16,6 +16,9 @@ using System.Web.Hosting; namespace Umbraco.Core { + + //TODO: Get the App_Code stuff in here from the old one + /// /// A utility class to find all classes of a certain type by reflection in the current bin folder /// of the web application. @@ -252,6 +255,32 @@ namespace Umbraco.Core return FindClassesOfType(new[] { assembly }); } + public IEnumerable FindClassesOfTypeWithAttribute() + where TAttribute : Attribute + { + return FindClassesOfTypeWithAttribute(GetAssembliesWithKnownExclusions(), true); + } + + public IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies) + where TAttribute : Attribute + { + return FindClassesOfTypeWithAttribute(assemblies, true); + } + + public IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses) + where TAttribute : Attribute + { + if (assemblies == null) throw new ArgumentNullException("assemblies"); + + return (from a in assemblies + from t in GetTypesWithFormattedException(a) + where !t.IsInterface + && typeof(T).IsAssignableFrom(t) + && t.GetCustomAttributes(false).Any() + && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract)) + select t).ToList(); + } + /// /// Searches all filtered local assemblies specified for classes of the type passed in. /// @@ -262,32 +291,6 @@ namespace Umbraco.Core return FindClassesOfType(GetAssembliesWithKnownExclusions(), true); } - /// - /// Searches all assemblies specified for classes of the type passed in. - /// - /// - /// - /// - public IEnumerable FindClassesOfType(IEnumerable assemblyFiles) - { - return FindClassesOfType(assemblyFiles, true); - } - - /// - /// Searches all assemblies specified for classes of the type passed in. - /// - /// - /// - /// Only resolve concrete classes that can be instantiated - /// - public IEnumerable FindClassesOfType(IEnumerable assemblyFiles, bool onlyConcreteClasses) - { - if (assemblyFiles == null) throw new ArgumentNullException("assemblyFiles"); - - var typeAndAssembly = GetAssignablesFromType(assemblyFiles, onlyConcreteClasses); - return GetTypesFromResult(typeAndAssembly); - } - /// /// Returns all types found of in the assemblies specified of type T /// @@ -354,40 +357,6 @@ namespace Umbraco.Core return FindClassesWithAttribute(GetAssembliesWithKnownExclusions()); } - #region Internal Methods - For testing - /// - /// Used to find all types in all assemblies in the specified folder - /// - /// - /// - /// - /// - /// - /// This has potential cost alot in performance so it is marked internal and should ONLY be used - /// where absolutely necessary (i.e. Tests) - /// - internal IEnumerable FindClassesOfType(DirectoryInfo folder, bool onlyConcreteClasses) - { - var types = new List(); - types.AddRange(FindClassesOfType(folder.GetFiles("*.dll").Select(x => x.FullName))); - return types; - } - - /// - /// Used to find all types in all assemblies in the specified folder - /// - /// - /// - /// - /// - /// This has potential cost alot in performance so it is marked internal and should ONLY be used - /// where absolutely necessary (i.e. Tests) - /// - internal IEnumerable FindClassesOfType(DirectoryInfo folder) - { - return FindClassesOfType(folder, true); - } - #endregion #region Internal Attributed Assembly class diff --git a/src/Umbraco.Tests/TypeFinderBenchmarkTests.cs b/src/Umbraco.Tests/TypeFinderBenchmarkTests.cs index 7ad7277ca6..97954bcb85 100644 --- a/src/Umbraco.Tests/TypeFinderBenchmarkTests.cs +++ b/src/Umbraco.Tests/TypeFinderBenchmarkTests.cs @@ -16,16 +16,15 @@ using umbraco.businesslogic; using umbraco.cms.businesslogic; using umbraco.uicontrols; -[assembly: TypeFinderBenchmarkTests.AssemblyContainsPluginsAttribute] +[assembly: TypeFinderTests.AssemblyContainsPluginsAttribute] namespace Umbraco.Tests { /// /// Full Trust benchmark tests for typefinder and the old typefinder /// - [TestFixture] - [Ignore("This is a benchark test")] - public class TypeFinderBenchmarkTests + [TestFixture] + public class TypeFinderTests { /// /// List of assemblies to scan @@ -73,18 +72,43 @@ namespace Umbraco.Tests { } + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public class MyTestAttribute : Attribute + { + + } + public abstract class TestEditor { } + [MyTestAttribute] public class BenchmarkTestEditor : TestEditor { } + [MyTestAttribute] + public class MyOtherTestEditor : TestEditor + { + + } + + [Test] + public void Get_Type_With_Attribute() + { + + var finder2 = new Umbraco.Core.TypeFinder2(); + + var typesFound = finder2.FindClassesOfTypeWithAttribute(_assemblies); + + Assert.AreEqual(2, typesFound.Count()); + + } [Test] + [Ignore("This is a benchark test")] public void Benchmark_Old_TypeFinder_vs_New_TypeFinder_FindClassesWithAttribute() { var timer = new Stopwatch(); @@ -107,6 +131,7 @@ namespace Umbraco.Tests } [Test] + [Ignore("This is a benchark test")] public void Benchmark_Old_TypeFinder_vs_New_TypeFinder_FindClassesOfType() { var timer = new Stopwatch(); @@ -133,6 +158,7 @@ namespace Umbraco.Tests /// cache files created instead since this is clearly a TON faster. /// [Test] + [Ignore("This is a benchark test")] public void Benchmark_Finding_First_Type_In_Assemblies() { var timer = new Stopwatch(); diff --git a/src/umbraco.businesslogic/ApplicationRegistrar.cs b/src/umbraco.businesslogic/ApplicationRegistrar.cs index d8ee358a93..47139638f3 100644 --- a/src/umbraco.businesslogic/ApplicationRegistrar.cs +++ b/src/umbraco.businesslogic/ApplicationRegistrar.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Xml.Linq; +using Umbraco.Core; using umbraco.BusinessLogic.Utils; using umbraco.DataLayer; using umbraco.businesslogic; @@ -29,10 +30,9 @@ namespace umbraco.BusinessLogic public ApplicationRegistrar() { // Load all Applications by attribute and add them to the XML config - var typeFinder = new Umbraco.Core.TypeFinder2(); - var types = typeFinder.FindClassesOfType() - .Where(x => x.GetCustomAttributes(typeof(ApplicationAttribute), false).Any()); + var types = PluginTypeResolver.Current.ResolveApplications(); + //we can have multiple attributes so we'll query for them var attrs = types.Select(x => (ApplicationAttribute)x.GetCustomAttributes(typeof(ApplicationAttribute), false).Single()) .Where(x => Application.getByAlias(x.Alias) == null); diff --git a/src/umbraco.businesslogic/PluginTypeResolverExtensions.cs b/src/umbraco.businesslogic/PluginTypeResolverExtensions.cs index 924403820c..f3acbfd55e 100644 --- a/src/umbraco.businesslogic/PluginTypeResolverExtensions.cs +++ b/src/umbraco.businesslogic/PluginTypeResolverExtensions.cs @@ -20,5 +20,15 @@ namespace umbraco.businesslogic return resolver.ResolveTypes(); } + /// + /// Returns all available IApplication object + /// + /// + /// + internal static IEnumerable ResolveApplications(this PluginTypeResolver resolver) + { + return resolver.ResolveTypesWithAttribute(); + } + } } \ No newline at end of file