Have removed ResolverBase as we cannot rely on manually setting the current singleton object since applications outside of the standard umbraco web application might be using these singletons and would expect they already be setup. Have changed all current resolvers to manage their own singleton instances and sealed them.
100 lines
2.8 KiB
C#
100 lines
2.8 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using Umbraco.Core.Resolving;
|
|
using umbraco.interfaces;
|
|
|
|
namespace Umbraco.Core
|
|
{
|
|
internal sealed class CacheRefreshersResolver : ManyObjectResolverBase<ICacheRefresher>
|
|
{
|
|
|
|
#region Singleton
|
|
|
|
private static readonly CacheRefreshersResolver Instance = new CacheRefreshersResolver(PluginTypeResolver.Current.ResolveCacheRefreshers());
|
|
|
|
public static CacheRefreshersResolver Current
|
|
{
|
|
get { return Instance; }
|
|
}
|
|
#endregion
|
|
|
|
#region Constructors
|
|
static CacheRefreshersResolver() { }
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="refreshers"></param>
|
|
/// <remarks>
|
|
/// We are creating Transient instances (new instances each time) because this is how the legacy code worked and
|
|
/// I don't want to muck anything up by changing them to application based instances.
|
|
/// TODO: However, it would make much more sense to do this and would speed up the application plus this would make the GetById method much easier.
|
|
/// </remarks>
|
|
internal CacheRefreshersResolver(IEnumerable<Type> refreshers)
|
|
: base(true)
|
|
{
|
|
foreach (var l in refreshers)
|
|
{
|
|
this.Add(l);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Maintains a list of Ids and their types when first call to CacheResolvers or GetById occurs, this is used
|
|
/// in order to return a single object by id without instantiating the entire type stack.
|
|
/// </summary>
|
|
private static ConcurrentDictionary<Guid, Type> _refreshers;
|
|
private readonly ReaderWriterLockSlim _lock= new ReaderWriterLockSlim();
|
|
|
|
/// <summary>
|
|
/// Gets the <see cref="ICacheRefresher"/> implementations.
|
|
/// </summary>
|
|
public IEnumerable<ICacheRefresher> CacheResolvers
|
|
{
|
|
get
|
|
{
|
|
EnsureRefreshersList();
|
|
return Values;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a new ICacheRefresher instance by id
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <returns></returns>
|
|
public ICacheRefresher GetById(Guid id)
|
|
{
|
|
EnsureRefreshersList();
|
|
return !_refreshers.ContainsKey(id)
|
|
? null
|
|
: PluginTypeResolver.Current.CreateInstance<ICacheRefresher>(_refreshers[id]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Populates the refreshers dictionary to allow us to instantiate a type by Id since the ICacheRefresher type doesn't contain any metadata
|
|
/// </summary>
|
|
private void EnsureRefreshersList()
|
|
{
|
|
using (var l = new UpgradeableReadLock(_lock))
|
|
{
|
|
if (_refreshers == null)
|
|
{
|
|
l.UpgradeToWriteLock();
|
|
_refreshers = new ConcurrentDictionary<Guid, Type>();
|
|
foreach(var v in Values)
|
|
{
|
|
_refreshers.TryAdd(v.UniqueIdentifier, v.GetType());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|