2012-08-01 10:05:39 +06:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
|
2012-08-10 13:18:13 +06:00
|
|
|
namespace Umbraco.Core.ObjectResolution
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A base resolver used for old legacy factories such as the DataTypeFactory or CacheResolverFactory.
|
|
|
|
|
/// </summary>
|
2012-08-01 22:06:15 +06:00
|
|
|
/// <typeparam name="TResolver"></typeparam>
|
|
|
|
|
/// <typeparam name="TResolved"> </typeparam>
|
2012-08-01 10:05:39 +06:00
|
|
|
/// <remarks>
|
|
|
|
|
/// This class contains basic functionality to mimic the functionality in these old factories since they all return
|
|
|
|
|
/// transient objects (though this should be changed) and the method GetById needs to lookup a type to an ID and since
|
|
|
|
|
/// these old classes don't contain metadata, the objects need to be instantiated first to get their metadata, we then store this
|
|
|
|
|
/// for use in the GetById method.
|
|
|
|
|
/// </remarks>
|
2012-08-01 22:06:15 +06:00
|
|
|
internal abstract class LegacyTransientObjectsResolver<TResolver, TResolved> : ManyObjectsResolverBase<TResolver, TResolved>
|
|
|
|
|
where TResolved : class
|
|
|
|
|
where TResolver : class
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
|
|
|
|
/// <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>
|
|
|
|
|
protected LegacyTransientObjectsResolver(IEnumerable<Type> refreshers)
|
2012-10-11 02:30:48 +05:00
|
|
|
: base(ObjectLifetimeScope.Transient) // new objects every time
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
|
|
|
|
foreach (var l in refreshers)
|
|
|
|
|
{
|
2012-08-01 10:48:19 +06:00
|
|
|
this.AddType(l);
|
2012-08-01 10:05:39 +06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#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 ConcurrentDictionary<Guid, Type> _trackIdToType;
|
|
|
|
|
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// method to return the unique id for type T
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="obj"></param>
|
|
|
|
|
/// <returns></returns>
|
2012-08-01 22:06:15 +06:00
|
|
|
protected abstract Guid GetUniqueIdentifier(TResolved obj);
|
2012-08-01 10:05:39 +06:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns a new ICacheRefresher instance by id
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id"></param>
|
|
|
|
|
/// <returns></returns>
|
2012-08-01 22:06:15 +06:00
|
|
|
public TResolved GetById(Guid id)
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
|
|
|
|
EnsureRefreshersList();
|
|
|
|
|
return !_trackIdToType.ContainsKey(id)
|
|
|
|
|
? null
|
2012-08-01 22:06:15 +06:00
|
|
|
: PluginManager.Current.CreateInstance<TResolved>(_trackIdToType[id]);
|
2012-08-01 10:05:39 +06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Populates the refreshers dictionary to allow us to instantiate a type by Id since the ICacheRefresher type doesn't contain any metadata
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected void EnsureRefreshersList()
|
|
|
|
|
{
|
|
|
|
|
using (var l = new UpgradeableReadLock(_lock))
|
|
|
|
|
{
|
|
|
|
|
if (_trackIdToType == null)
|
|
|
|
|
{
|
|
|
|
|
l.UpgradeToWriteLock();
|
|
|
|
|
_trackIdToType = new ConcurrentDictionary<Guid, Type>();
|
|
|
|
|
foreach (var v in Values)
|
|
|
|
|
{
|
|
|
|
|
_trackIdToType.TryAdd(GetUniqueIdentifier(v), v.GetType());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|