Updated TreeDefinitionCollection to use PluginTypeResolver and fixed its code to be thread safe.
Updated restExtensions to use PluginTypeResolver and added unit test for resolving these types. Updated TypeFinder2 with a slight perf increase.
This commit is contained in:
@@ -177,6 +177,17 @@ namespace Umbraco.Core
|
||||
return ResolveTypes<T>(() => TypeFinder.FindClassesOfTypeWithAttribute<T, TAttribute>(AssembliesToScan));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic method to find any type that has the specified attribute
|
||||
/// </summary>
|
||||
/// <typeparam name="TAttribute"></typeparam>
|
||||
/// <returns></returns>
|
||||
internal IEnumerable<Type> ResolveAttributedTypes<TAttribute>()
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
return ResolveTypes<object>(() => TypeFinder.FindClassesWithAttribute<TAttribute>(AssembliesToScan));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for unit tests
|
||||
/// </summary>
|
||||
|
||||
@@ -269,13 +269,19 @@ namespace Umbraco.Core
|
||||
{
|
||||
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();
|
||||
var l = new List<Type>();
|
||||
foreach(var a in assemblies)
|
||||
{
|
||||
var types = from t in GetTypesWithFormattedException(a)
|
||||
where !t.IsInterface
|
||||
&& typeof (T).IsAssignableFrom(t)
|
||||
&& t.GetCustomAttributes<TAttribute>(false).Any()
|
||||
&& (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
|
||||
select t;
|
||||
l.AddRange(types);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -325,10 +331,16 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (assemblies == null) throw new ArgumentNullException("assemblies");
|
||||
|
||||
return (from a in assemblies
|
||||
from t in GetTypesWithFormattedException(a)
|
||||
where !t.IsInterface && t.GetCustomAttributes<T>(false).Any() && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
|
||||
select t).ToList();
|
||||
var l = new List<Type>();
|
||||
foreach (var a in assemblies)
|
||||
{
|
||||
var types = from t in GetTypesWithFormattedException(a)
|
||||
where !t.IsInterface && t.GetCustomAttributes<T>(false).Any() && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
|
||||
select t;
|
||||
l.AddRange(types);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -430,10 +442,15 @@ namespace Umbraco.Core
|
||||
|
||||
private static IEnumerable<Type> GetTypes(Type assignTypeFrom, IEnumerable<Assembly> assemblies, bool onlyConcreteClasses)
|
||||
{
|
||||
return (from a in assemblies
|
||||
from t in GetTypesWithFormattedException(a)
|
||||
where !t.IsInterface && assignTypeFrom.IsAssignableFrom(t) && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
|
||||
select t).ToList();
|
||||
var l = new List<Type>();
|
||||
foreach (var a in assemblies)
|
||||
{
|
||||
var types = from t in GetTypesWithFormattedException(a)
|
||||
where !t.IsInterface && assignTypeFrom.IsAssignableFrom(t) && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract))
|
||||
select t;
|
||||
l.AddRange(types);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
private static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
|
||||
|
||||
@@ -9,6 +9,7 @@ using umbraco.MacroEngines.Iron;
|
||||
using umbraco.businesslogic;
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.editorControls;
|
||||
using umbraco.presentation.umbracobase;
|
||||
using umbraco.uicontrols;
|
||||
using umbraco.cms;
|
||||
|
||||
@@ -42,8 +43,7 @@ namespace Umbraco.Tests
|
||||
typeof(DLRScriptingEngine).Assembly,
|
||||
typeof(ICultureDictionary).Assembly,
|
||||
typeof(UmbracoContext).Assembly,
|
||||
typeof(BaseDataType).Assembly,
|
||||
typeof(DynamicNode).Assembly
|
||||
typeof(BaseDataType).Assembly
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,6 +62,13 @@ namespace Umbraco.Tests
|
||||
Assert.AreEqual(2, foundTypes1.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Attributed_Trees()
|
||||
{
|
||||
var trees = PluginTypeResolver.Current.ResolveAttributedTrees();
|
||||
Assert.AreEqual(26, trees.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Trees()
|
||||
{
|
||||
@@ -87,14 +94,27 @@ namespace Umbraco.Tests
|
||||
public void Resolves_DataTypes()
|
||||
{
|
||||
var types = PluginTypeResolver.Current.ResolveDataTypes();
|
||||
Assert.AreEqual(33, types.Count());
|
||||
Assert.AreEqual(36, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_RazorDataTypeModels()
|
||||
{
|
||||
var types = PluginTypeResolver.Current.ResolveRazorDataTypeModels();
|
||||
Assert.AreEqual(3, types.Count());
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_RestExtensions()
|
||||
{
|
||||
var types = PluginTypeResolver.Current.ResolveRestExtensions();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
|
||||
[RestExtension("Blah")]
|
||||
public class MyTestExtension
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IFindMe
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco.interfaces;
|
||||
using umbraco.presentation.umbracobase;
|
||||
|
||||
|
||||
namespace Umbraco.Web
|
||||
@@ -12,16 +14,24 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
public static class PluginTypeResolverExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all available ITrees in application
|
||||
/// </summary>
|
||||
/// <param name="resolver"></param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<Type> ResolveTrees(this PluginTypeResolver resolver)
|
||||
{
|
||||
return resolver.ResolveTypes<ITree>();
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Returns all IDocumentLookup types
|
||||
///// </summary>
|
||||
///// <param name="resolver"></param>
|
||||
///// <returns></returns>
|
||||
//internal static IEnumerable<Type> ResolveLookups(this PluginTypeResolver resolver)
|
||||
//{
|
||||
// return resolver.ResolveTypes<IDocumentLookup>();
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all classes attributed with RestExtension attribute
|
||||
/// </summary>
|
||||
/// <param name="resolver"></param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<Type> ResolveRestExtensions(this PluginTypeResolver resolver)
|
||||
{
|
||||
return resolver.ResolveAttributedTypes<RestExtension>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Configuration;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
@@ -8,6 +9,8 @@ using System.Web.UI.WebControls;
|
||||
using System.Web.UI.WebControls.WebParts;
|
||||
using System.Web.UI.HtmlControls;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web;
|
||||
using umbraco.interfaces;
|
||||
using umbraco.BusinessLogic.Utils;
|
||||
using umbraco.BusinessLogic;
|
||||
@@ -23,6 +26,9 @@ namespace umbraco.cms.presentation.Trees
|
||||
|
||||
//create singleton
|
||||
private static readonly TreeDefinitionCollection instance = new TreeDefinitionCollection();
|
||||
|
||||
private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
|
||||
|
||||
private TreeDefinitionCollection()
|
||||
{
|
||||
RegisterTrees();
|
||||
@@ -42,12 +48,9 @@ namespace umbraco.cms.presentation.Trees
|
||||
/// <returns></returns>
|
||||
public TreeDefinition FindTree(ITree tree)
|
||||
{
|
||||
TreeDefinition foundTree = this.Find(
|
||||
delegate(TreeDefinition t)
|
||||
{
|
||||
return t.TreeType.Equals(tree.GetType());
|
||||
}
|
||||
);
|
||||
var foundTree = this.Find(
|
||||
t => t.TreeType == tree.GetType()
|
||||
);
|
||||
if (foundTree != null)
|
||||
return foundTree;
|
||||
|
||||
@@ -61,7 +64,7 @@ namespace umbraco.cms.presentation.Trees
|
||||
/// <returns></returns>
|
||||
public TreeDefinition FindTree<T>() where T : ITree
|
||||
{
|
||||
TreeDefinition foundTree = this.Find(
|
||||
var foundTree = this.Find(
|
||||
delegate(TreeDefinition t)
|
||||
{
|
||||
// zb-00002 #29929 : use IsAssignableFrom instead of Equal, otherwise you can't override build-in
|
||||
@@ -79,16 +82,12 @@ namespace umbraco.cms.presentation.Trees
|
||||
/// Return the TreeDefinition object based on the tree alias and application it belongs to
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <param name="appAlias"></param>
|
||||
/// <returns></returns>
|
||||
public TreeDefinition FindTree(string alias)
|
||||
{
|
||||
TreeDefinition foundTree = this.Find(
|
||||
delegate(TreeDefinition t)
|
||||
{
|
||||
return t.Tree.Alias.ToLower() == alias.ToLower();
|
||||
}
|
||||
);
|
||||
var foundTree = this.Find(
|
||||
t => t.Tree.Alias.ToLower() == alias.ToLower()
|
||||
);
|
||||
if (foundTree != null)
|
||||
return foundTree;
|
||||
|
||||
@@ -103,11 +102,8 @@ namespace umbraco.cms.presentation.Trees
|
||||
public List<TreeDefinition> FindTrees(string appAlias)
|
||||
{
|
||||
return this.FindAll(
|
||||
delegate(TreeDefinition tree)
|
||||
{
|
||||
return (tree.App != null && tree.App.alias.ToLower() == appAlias.ToLower());
|
||||
}
|
||||
);
|
||||
tree => (tree.App != null && tree.App.alias.ToLower() == appAlias.ToLower())
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -118,17 +114,13 @@ namespace umbraco.cms.presentation.Trees
|
||||
public List<TreeDefinition> FindActiveTrees(string appAlias)
|
||||
{
|
||||
return this.FindAll(
|
||||
delegate(TreeDefinition tree)
|
||||
{
|
||||
return (tree.App != null && tree.App.alias.ToLower() == appAlias.ToLower() && tree.Tree.Initialize);
|
||||
}
|
||||
);
|
||||
tree => (tree.App != null && tree.App.alias.ToLower() == appAlias.ToLower() && tree.Tree.Initialize)
|
||||
);
|
||||
}
|
||||
|
||||
public void ReRegisterTrees()
|
||||
{
|
||||
this.Clear();
|
||||
RegisterTrees();
|
||||
RegisterTrees(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -137,57 +129,55 @@ namespace umbraco.cms.presentation.Trees
|
||||
/// This will also store an instance of each tree object in the TreeDefinition class which should be
|
||||
/// used when referencing all tree classes.
|
||||
/// </summary>
|
||||
private void RegisterTrees()
|
||||
private void RegisterTrees(bool clearFirst = false)
|
||||
{
|
||||
using (var l = new UpgradeableReadLock(Lock))
|
||||
{
|
||||
if (clearFirst)
|
||||
{
|
||||
this.Clear();
|
||||
}
|
||||
|
||||
if (this.Count > 0)
|
||||
return;
|
||||
//if we already have tree, exit
|
||||
if (this.Count > 0)
|
||||
return;
|
||||
|
||||
var typeFinder = new Umbraco.Core.TypeFinder2();
|
||||
var foundITrees = typeFinder.FindClassesOfType<ITree>();
|
||||
l.UpgradeToWriteLock();
|
||||
|
||||
ApplicationTree[] objTrees = ApplicationTree.getAll();
|
||||
var appTrees = new List<ApplicationTree>();
|
||||
appTrees.AddRange(objTrees);
|
||||
|
||||
List<Application> apps = Application.getAll();
|
||||
var foundITrees = PluginTypeResolver.Current.ResolveTrees();
|
||||
|
||||
foreach (Type type in foundITrees)
|
||||
{
|
||||
var objTrees = ApplicationTree.getAll();
|
||||
var appTrees = new List<ApplicationTree>();
|
||||
appTrees.AddRange(objTrees);
|
||||
|
||||
//find the Application tree's who's combination of assembly name and tree type is equal to
|
||||
//the Type that was found's full name.
|
||||
//Since a tree can exist in multiple applications we'll need to register them all.
|
||||
List<ApplicationTree> appTreesForType = appTrees.FindAll(
|
||||
delegate(ApplicationTree tree)
|
||||
{
|
||||
return (string.Format("{0}.{1}", tree.AssemblyName, tree.Type) == type.FullName);
|
||||
}
|
||||
);
|
||||
|
||||
if (appTreesForType != null)
|
||||
{
|
||||
foreach (ApplicationTree appTree in appTreesForType)
|
||||
{
|
||||
//find the Application object whos name is the same as our appTree ApplicationAlias
|
||||
Application app = apps.Find(
|
||||
delegate(Application a)
|
||||
{
|
||||
return (a.alias == appTree.ApplicationAlias);
|
||||
}
|
||||
var apps = Application.getAll();
|
||||
|
||||
foreach (var type in foundITrees)
|
||||
{
|
||||
|
||||
//find the Application tree's who's combination of assembly name and tree type is equal to
|
||||
//the Type that was found's full name.
|
||||
//Since a tree can exist in multiple applications we'll need to register them all.
|
||||
var appTreesForType = appTrees.FindAll(
|
||||
tree => (string.Format("{0}.{1}", tree.AssemblyName, tree.Type) == type.FullName)
|
||||
);
|
||||
|
||||
TreeDefinition def = new TreeDefinition(type, appTree, app);
|
||||
foreach (var appTree in appTreesForType)
|
||||
{
|
||||
//find the Application object whos name is the same as our appTree ApplicationAlias
|
||||
var app = apps.Find(
|
||||
a => (a.alias == appTree.ApplicationAlias)
|
||||
);
|
||||
|
||||
var def = new TreeDefinition(type, appTree, app);
|
||||
this.Add(def);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//sort our trees with the sort order definition
|
||||
this.Sort(delegate(TreeDefinition t1, TreeDefinition t2)
|
||||
{
|
||||
return t1.Tree.SortOrder.CompareTo(t2.Tree.SortOrder);
|
||||
});
|
||||
}
|
||||
//sort our trees with the sort order definition
|
||||
this.Sort((t1, t2) => t1.Tree.SortOrder.CompareTo(t2.Tree.SortOrder));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web;
|
||||
using umbraco.BusinessLogic.Utils;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
using umbraco.IO;
|
||||
@@ -95,8 +97,9 @@ namespace umbraco.presentation.umbracobase
|
||||
{
|
||||
//check for RestExtensionAttribute
|
||||
|
||||
var typeFinder = new Umbraco.Core.TypeFinder2();
|
||||
foreach (var t in typeFinder.FindClassesWithAttribute<RestExtension>())
|
||||
var restExtensions = PluginTypeResolver.Current.ResolveRestExtensions();
|
||||
|
||||
foreach (var t in restExtensions)
|
||||
{
|
||||
|
||||
var temp = t.GetCustomAttributes(typeof(RestExtension), false).OfType<RestExtension>();
|
||||
@@ -109,7 +112,9 @@ namespace umbraco.presentation.umbracobase
|
||||
if (mi != null)
|
||||
{
|
||||
//check allowed
|
||||
var attributes = mi.GetCustomAttributes(typeof(RestExtensionMethod), false).OfType<RestExtensionMethod>();
|
||||
var attributes = mi.GetCustomAttributes(typeof (RestExtensionMethod), false)
|
||||
.OfType<RestExtensionMethod>()
|
||||
.ToArray();
|
||||
|
||||
//check to make sure the method was decorated properly
|
||||
if (attributes.Any())
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace umbraco.BusinessLogic
|
||||
public ApplicationTreeRegistrar()
|
||||
{
|
||||
// Load all Trees by attribute and add them to the XML config
|
||||
var types = PluginTypeResolver.Current.ResolveTrees();
|
||||
var types = PluginTypeResolver.Current.ResolveAttributedTrees();
|
||||
|
||||
var items = types
|
||||
.Select(x =>
|
||||
|
||||
@@ -31,14 +31,16 @@ namespace umbraco.businesslogic
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all available ITrees in application
|
||||
/// Returns all available ITrees in application that are attribute with TreeAttribute
|
||||
/// </summary>
|
||||
/// <param name="resolver"></param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<Type> ResolveTrees(this PluginTypeResolver resolver)
|
||||
internal static IEnumerable<Type> ResolveAttributedTrees(this PluginTypeResolver resolver)
|
||||
{
|
||||
return resolver.ResolveTypesWithAttribute<ITree, TreeAttribute>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user