Updated DataType factory to use PluginTypeResolver and made the dictionary thread safe.

Updated MacroEngineFactory to use PluginTypeResolver and made it thread safe. Have also
updated it to only create one instance of each IMacroEngine per application which should
increase performance a teeny bit, plus that's how it should be.
This commit is contained in:
shannon@ShandemVaio
2012-07-27 11:54:29 +06:00
parent 1823cce4f6
commit 5576f65ef0
9 changed files with 169 additions and 97 deletions

View File

@@ -104,6 +104,19 @@ namespace Umbraco.Core
return instances;
}
/// <summary>
/// Used to create an instance of the specified type based on the resolved/cached plugin types
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="throwException"></param>
/// <returns></returns>
internal T CreateInstance<T>(Type type, bool throwException = false)
{
var instances = CreateInstances<T>(new[] {type}, throwException);
return instances.FirstOrDefault();
}
private IEnumerable<Type> ResolveTypes<T>(Func<IEnumerable<Type>> finder)
{
using (var readLock = new UpgradeableReadLock(_lock))

View File

@@ -3,6 +3,9 @@ using System.Threading;
namespace Umbraco.Core.Resolving
{
//NOTE: This class should also support creating instances of the object and managing their lifespan,
// for example, some resolvers would want to return new object each time, per request or per application lifetime.
/// <summary>
/// A Resolver to return and set a Multiply registered object.
/// </summary>

View File

@@ -0,0 +1,63 @@
using NUnit.Framework;
using SqlCE4Umbraco;
using Umbraco.Core;
using Umbraco.Web;
using umbraco.DataLayer;
using umbraco.MacroEngines;
using umbraco.MacroEngines.Iron;
using umbraco.businesslogic;
using umbraco.cms.businesslogic;
using umbraco.editorControls;
using umbraco.uicontrols;
using System.Linq;
namespace Umbraco.Tests
{
[TestFixture]
public class DataTypeFactoryTests
{
[SetUp]
public void Initialize()
{
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginTypeResolver.Current.AssembliesToScan = new[]
{
this.GetType().Assembly,
typeof(ApplicationStartupHandler).Assembly,
typeof(SqlCEHelper).Assembly,
typeof(CMSNode).Assembly,
typeof(System.Guid).Assembly,
typeof(NUnit.Framework.Assert).Assembly,
typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly,
typeof(System.Xml.NameTable).Assembly,
typeof(System.Configuration.GenericEnumConverter).Assembly,
typeof(System.Web.SiteMap).Assembly,
typeof(TabPage).Assembly,
typeof(System.Web.Mvc.ActionResult).Assembly,
typeof(TypeFinder2).Assembly,
typeof(ISqlHelper).Assembly,
typeof(DLRScriptingEngine).Assembly,
typeof(ICultureDictionary).Assembly,
typeof(UmbracoContext).Assembly,
typeof(BaseDataType).Assembly,
};
}
[Test]
public void Find_All_DataTypes()
{
umbraco.cms.businesslogic.datatype.controls.Factory.Initialize();
Assert.AreEqual(33, umbraco.cms.businesslogic.datatype.controls.Factory._controls.Count);
}
[Test]
public void Get_All_Instances()
{
umbraco.cms.businesslogic.datatype.controls.Factory.Initialize();
var factory = new umbraco.cms.businesslogic.datatype.controls.Factory();
Assert.AreEqual(33, factory.GetAll().Count());
}
}
}

View File

@@ -8,7 +8,6 @@ using Umbraco.Core.Resolving;
namespace Umbraco.Tests
{
[TestFixture]
public class EnumerableExtensionsTests
{

View File

@@ -8,6 +8,7 @@ using umbraco.MacroEngines;
using umbraco.MacroEngines.Iron;
using umbraco.businesslogic;
using umbraco.cms.businesslogic;
using umbraco.editorControls;
using umbraco.uicontrols;
using umbraco.cms;
@@ -40,8 +41,8 @@ namespace Umbraco.Tests
typeof(ISqlHelper).Assembly,
typeof(DLRScriptingEngine).Assembly,
typeof(ICultureDictionary).Assembly,
typeof(UmbracoContext).Assembly
typeof(UmbracoContext).Assembly,
typeof(BaseDataType).Assembly
};
}
@@ -81,6 +82,13 @@ namespace Umbraco.Tests
Assert.AreEqual(1, types.Count());
}
[Test]
public void Resolves_DataTypes()
{
var types = PluginTypeResolver.Current.ResolveDataTypes();
Assert.AreEqual(33, types.Count());
}
public interface IFindMe
{

View File

@@ -49,6 +49,7 @@
<Compile Include="BusinessLogic\ApplicationTest.cs" />
<Compile Include="BusinessLogic\ApplicationTreeTest.cs" />
<Compile Include="BusinessLogic\BaseTest.cs" />
<Compile Include="DataTypeFactoryTests.cs" />
<Compile Include="PluginTypeResolverExtensions.cs" />
<Compile Include="PluginTypeResolverTests.cs" />
<Compile Include="TestHelper.cs" />
@@ -92,6 +93,10 @@
<Project>{C7CB79F0-1C97-4B33-BFA7-00731B579AE2}</Project>
<Name>umbraco.datalayer</Name>
</ProjectReference>
<ProjectReference Include="..\umbraco.editorControls\umbraco.editorControls.csproj">
<Project>{255F5DF1-4E43-4758-AC05-7A0B68EB021B}</Project>
<Name>umbraco.editorControls</Name>
</ProjectReference>
<ProjectReference Include="..\umbraco.interfaces\umbraco.interfaces.csproj">
<Project>{511F6D8D-7717-440A-9A57-A507E9A8B27F}</Project>
<Name>umbraco.interfaces</Name>

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using Umbraco.Core;
using umbraco.BusinessLogic.Actions;
using umbraco.businesslogic;
using umbraco.cms.businesslogic.macro;
using umbraco.interfaces;
namespace umbraco.cms
@@ -23,5 +24,25 @@ namespace umbraco.cms
return resolver.ResolveTypes<IActionHandler>();
}
/// <summary>
/// Returns all available IDataType in application
/// </summary>
/// <param name="resolver"></param>
/// <returns></returns>
internal static IEnumerable<Type> ResolveDataTypes(this PluginTypeResolver resolver)
{
return resolver.ResolveTypes<IDataType>();
}
/// <summary>
/// Returns all available IDataType in application
/// </summary>
/// <param name="resolver"></param>
/// <returns></returns>
internal static IEnumerable<Type> ResolveMacroEngines(this PluginTypeResolver resolver)
{
return resolver.ResolveTypes<IMacroEngine>();
}
}
}

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Linq;
using System.Web;
using Umbraco.Core;
using umbraco.BusinessLogic.Utils;
using umbraco.interfaces;
using System.Collections.Generic;
@@ -17,7 +19,7 @@ namespace umbraco.cms.businesslogic.datatype.controls
{
#region Declarations
private static readonly Dictionary<Guid, Type> _controls = new Dictionary<Guid, Type>();
internal static readonly ConcurrentDictionary<Guid, Type> _controls = new ConcurrentDictionary<Guid, Type>();
#endregion
@@ -53,7 +55,7 @@ namespace umbraco.cms.businesslogic.datatype.controls
}
if (_controls.ContainsKey(DataEditorId))
{
IDataType newObject = Activator.CreateInstance(_controls[DataEditorId]) as IDataType;
var newObject = PluginTypeResolver.Current.CreateInstance<IDataType>(_controls[DataEditorId]);
return newObject;
}
else
@@ -68,10 +70,10 @@ namespace umbraco.cms.businesslogic.datatype.controls
/// <returns>A list of IDataType's</returns>
public IDataType[] GetAll()
{
IDataType[] retVal = new IDataType[_controls.Count];
int c = 0;
var retVal = new IDataType[_controls.Count];
var c = 0;
foreach (Guid id in _controls.Keys)
foreach (var id in _controls.Keys)
{
retVal[c] = GetNewObject(id);
c++;
@@ -80,39 +82,19 @@ namespace umbraco.cms.businesslogic.datatype.controls
return retVal;
}
private static void Initialize()
internal static void Initialize()
{
// Get all datatypes from interface
var typeFinder = new Umbraco.Core.TypeFinder2();
var types = typeFinder.FindClassesOfType<IDataType>();
GetDataTypes(types);
}
private static void GetDataTypes(IEnumerable<Type> types)
{
foreach (var t in types)
{
IDataType typeInstance = null;
try
{
if (t.IsVisible)
{
typeInstance = Activator.CreateInstance(t) as IDataType;
}
}
catch { }
if (typeInstance != null)
{
try
{
_controls.Add(typeInstance.Id, t);
}
catch (Exception ee)
{
BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Error, -1, "Can't import datatype '" + t.FullName + "': " + ee.ToString());
}
}
}
var types = PluginTypeResolver.Current.ResolveDataTypes().ToArray();
foreach (var t in types)
{
var instance = PluginTypeResolver.Current.CreateInstance<IDataType>(t);
if (instance != null)
{
_controls.TryAdd(instance.Id, t);
}
}
}
}
}

View File

@@ -1,59 +1,50 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Umbraco.Core;
using umbraco.BusinessLogic.Utils;
using umbraco.interfaces;
namespace umbraco.cms.businesslogic.macro
{
//TODO: This class needs to be changed to use the new MultipleResolverBase
public class MacroEngineFactory
{
private static readonly Dictionary<string, Type> m_engines = new Dictionary<string, Type>();
private static readonly List<IMacroEngine> m_allEngines = new List<IMacroEngine>();
private static object locker = new object();
private static readonly List<IMacroEngine> AllEngines = new List<IMacroEngine>();
private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
private static volatile bool _isInitialized = false;
public MacroEngineFactory()
{
Initialize();
EnsureInitialize();
}
internal static void EnsureInitialize()
{
if (_isInitialized)
return;
using (new WriteLock(Lock))
{
AllEngines.Clear();
AllEngines.AddRange(
PluginTypeResolver.Current.CreateInstances<IMacroEngine>(
PluginTypeResolver.Current.ResolveMacroEngines()));
_isInitialized = true;
}
}
[Obsolete("Use EnsureInitialize method instead")]
protected static void Initialize()
{
var typeFinder = new Umbraco.Core.TypeFinder2();
var types = typeFinder.FindClassesOfType<IMacroEngine>();
GetEngines(types);
}
private static void GetEngines(IEnumerable<Type> types)
{
foreach (Type t in types)
{
IMacroEngine typeInstance = null;
try
{
if (t.IsVisible)
{
typeInstance = Activator.CreateInstance(t) as IMacroEngine;
}
}
catch { }
if (typeInstance != null)
{
try
{
lock (locker)
{
if (!m_engines.ContainsKey(typeInstance.Name))
m_engines.Add(typeInstance.Name, t);
}
}
catch (Exception ee)
{
BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Error, -1, "Can't import MacroEngine '" + t.FullName + "': " + ee);
}
}
}
EnsureInitialize();
}
public static IEnumerable<MacroEngineLanguage> GetSupportedLanguages() {
@@ -78,27 +69,15 @@ namespace umbraco.cms.businesslogic.macro
public static List<IMacroEngine> GetAll()
{
if (m_allEngines.Count == 0)
{
Initialize();
foreach (string name in m_engines.Keys) {
m_allEngines.Add(GetEngine(name));
}
}
return m_allEngines;
EnsureInitialize();
return AllEngines;
}
public static IMacroEngine GetEngine(string name)
{
if (m_engines.ContainsKey(name))
{
var newObject = Activator.CreateInstance(m_engines[name]) as IMacroEngine;
return newObject;
}
return null;
EnsureInitialize();
var engine = AllEngines.FirstOrDefault(x => x.Name == name);
return engine;
}
public static IMacroEngine GetByFilename(string filename)
@@ -114,8 +93,7 @@ namespace umbraco.cms.businesslogic.macro
public static IMacroEngine GetByExtension(string extension)
{
IMacroEngine engine =
GetAll().Find(t => t.SupportedExtensions.Contains(extension));
var engine = GetAll().Find(t => t.SupportedExtensions.Contains(extension));
if (engine != null)
{
return engine;