Added new TypeFinder methods for resolving types with attributes. Updated the PluginResolver to resolve IApplication

This commit is contained in:
shannon@ShandemVaio
2012-07-27 06:24:57 +06:00
parent 92f983a569
commit 58fbe9f4ab
5 changed files with 95 additions and 75 deletions

View File

@@ -73,14 +73,9 @@ namespace Umbraco.Core
}
}
return instances;
}
}
/// <summary>
/// Generic method to find the specified type and cache the result
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
internal IEnumerable<Type> ResolveTypes<T>()
private IEnumerable<Type> ResolveTypes<T>(Func<IEnumerable<Type>> finder)
{
using (var readLock = new UpgradeableReadLock(_lock))
{
@@ -93,7 +88,7 @@ namespace Umbraco.Core
typeList = new TypeList<T>();
foreach (var t in TypeFinder.FindClassesOfType<T>())
foreach (var t in finder())
{
typeList.AddType(t);
}
@@ -103,8 +98,28 @@ namespace Umbraco.Core
}
return typeList.GetTypes();
}
}
/// <summary>
/// Generic method to find the specified type and cache the result
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
internal IEnumerable<Type> ResolveTypes<T>()
{
return ResolveTypes<T>(() => TypeFinder.FindClassesOfType<T>());
}
/// <summary>
/// Generic method to find the specified type that has an attribute and cache the result
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TAttribute"></typeparam>
/// <returns></returns>
internal IEnumerable<Type> ResolveTypesWithAttribute<T, TAttribute>()
where TAttribute : Attribute
{
return ResolveTypes<T>(() => TypeFinder.FindClassesOfTypeWithAttribute<T, TAttribute>());
}
/// <summary>

View File

@@ -16,6 +16,9 @@ using System.Web.Hosting;
namespace Umbraco.Core
{
//TODO: Get the App_Code stuff in here from the old one
/// <summary>
/// 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<T, TAssemblyAttribute>(new[] { assembly });
}
public IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>()
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<T, TAttribute>(GetAssembliesWithKnownExclusions(), true);
}
public IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>(IEnumerable<Assembly> assemblies)
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<T, TAttribute>(assemblies, true);
}
public IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>(IEnumerable<Assembly> 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<TAttribute>(false).Any()
&& (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
select t).ToList();
}
/// <summary>
/// Searches all filtered local assemblies specified for classes of the type passed in.
/// </summary>
@@ -262,32 +291,6 @@ namespace Umbraco.Core
return FindClassesOfType<T>(GetAssembliesWithKnownExclusions(), true);
}
/// <summary>
/// Searches all assemblies specified for classes of the type passed in.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblyFiles"></param>
/// <returns></returns>
public IEnumerable<Type> FindClassesOfType<T>(IEnumerable<string> assemblyFiles)
{
return FindClassesOfType<T>(assemblyFiles, true);
}
/// <summary>
/// Searches all assemblies specified for classes of the type passed in.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblyFiles"></param>
/// <param name="onlyConcreteClasses">Only resolve concrete classes that can be instantiated</param>
/// <returns></returns>
public IEnumerable<Type> FindClassesOfType<T>(IEnumerable<string> assemblyFiles, bool onlyConcreteClasses)
{
if (assemblyFiles == null) throw new ArgumentNullException("assemblyFiles");
var typeAndAssembly = GetAssignablesFromType<T>(assemblyFiles, onlyConcreteClasses);
return GetTypesFromResult(typeAndAssembly);
}
/// <summary>
/// Returns all types found of in the assemblies specified of type T
/// </summary>
@@ -354,40 +357,6 @@ namespace Umbraco.Core
return FindClassesWithAttribute<T>(GetAssembliesWithKnownExclusions());
}
#region Internal Methods - For testing
/// <summary>
/// Used to find all types in all assemblies in the specified folder
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="folder"></param>
/// <param name="onlyConcreteClasses"></param>
/// <returns></returns>
/// <remarks>
/// This has potential cost alot in performance so it is marked internal and should ONLY be used
/// where absolutely necessary (i.e. Tests)
/// </remarks>
internal IEnumerable<Type> FindClassesOfType<T>(DirectoryInfo folder, bool onlyConcreteClasses)
{
var types = new List<Type>();
types.AddRange(FindClassesOfType<T>(folder.GetFiles("*.dll").Select(x => x.FullName)));
return types;
}
/// <summary>
/// Used to find all types in all assemblies in the specified folder
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="folder"></param>
/// <returns></returns>
/// <remarks>
/// This has potential cost alot in performance so it is marked internal and should ONLY be used
/// where absolutely necessary (i.e. Tests)
/// </remarks>
internal IEnumerable<Type> FindClassesOfType<T>(DirectoryInfo folder)
{
return FindClassesOfType<T>(folder, true);
}
#endregion
#region Internal Attributed Assembly class

View File

@@ -16,16 +16,15 @@ using umbraco.businesslogic;
using umbraco.cms.businesslogic;
using umbraco.uicontrols;
[assembly: TypeFinderBenchmarkTests.AssemblyContainsPluginsAttribute]
[assembly: TypeFinderTests.AssemblyContainsPluginsAttribute]
namespace Umbraco.Tests
{
/// <summary>
/// Full Trust benchmark tests for typefinder and the old typefinder
/// </summary>
[TestFixture]
[Ignore("This is a benchark test")]
public class TypeFinderBenchmarkTests
[TestFixture]
public class TypeFinderTests
{
/// <summary>
/// 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<TestEditor, MyTestAttribute>(_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.
/// </summary>
[Test]
[Ignore("This is a benchark test")]
public void Benchmark_Finding_First_Type_In_Assemblies()
{
var timer = new Stopwatch();

View File

@@ -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<IApplication>()
.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);

View File

@@ -20,5 +20,15 @@ namespace umbraco.businesslogic
return resolver.ResolveTypes<IApplicationStartupHandler>();
}
/// <summary>
/// Returns all available IApplication object
/// </summary>
/// <param name="resolver"></param>
/// <returns></returns>
internal static IEnumerable<Type> ResolveApplications(this PluginTypeResolver resolver)
{
return resolver.ResolveTypesWithAttribute<IApplication, ApplicationAttribute>();
}
}
}