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:
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
|
||||
63
src/Umbraco.Tests/DataTypeFactoryTests.cs
Normal file
63
src/Umbraco.Tests/DataTypeFactoryTests.cs
Normal 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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ using Umbraco.Core.Resolving;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class EnumerableExtensionsTests
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user