Core.ObjectsResolution - refactor, cleanup, sanitize, ensure we properly freeze
This commit is contained in:
@@ -7,10 +7,10 @@ using System.Threading;
|
||||
namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
/// <summary>
|
||||
/// A base resolver used for old legacy factories such as the DataTypeFactory or CacheResolverFactory.
|
||||
/// The base class for old legacy factories such as the DataTypeFactory or CacheResolverFactory.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResolver"></typeparam>
|
||||
/// <typeparam name="TResolved"> </typeparam>
|
||||
/// <typeparam name="TResolver">The type of the concrete resolver class.</typeparam>
|
||||
/// <typeparam name="TResolved">The type of the resolved objects.</typeparam>
|
||||
/// <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
|
||||
@@ -21,7 +21,9 @@ namespace Umbraco.Core.ObjectResolution
|
||||
where TResolved : class
|
||||
where TResolver : class
|
||||
{
|
||||
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
private ConcurrentDictionary<Guid, Type> _id2type;
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
@@ -40,46 +42,45 @@ namespace Umbraco.Core.ObjectResolution
|
||||
#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.
|
||||
/// Returns the unique identifier of the type of a specified object.
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<Guid, Type> _trackIdToType;
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
/// <param name="value">The object.</param>
|
||||
/// <returns>The unique identifier of the type of <paramref name="value"/>.</returns>
|
||||
protected abstract Guid GetUniqueIdentifier(TResolved value);
|
||||
|
||||
/// <summary>
|
||||
/// method to return the unique id for type T
|
||||
/// Returns a new instance for the type identified by its unique type identifier.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract Guid GetUniqueIdentifier(TResolved obj);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new TResolved instance by id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="id">The type identifier.</param>
|
||||
/// <returns>The value of the type uniquely identified by <paramref name="id"/>.</returns>
|
||||
public TResolved GetById(Guid id)
|
||||
{
|
||||
EnsureIdsAreTracked();
|
||||
return !_trackIdToType.ContainsKey(id)
|
||||
EnsureIsInitialized();
|
||||
return !_id2type.ContainsKey(id)
|
||||
? null
|
||||
: PluginManager.Current.CreateInstance<TResolved>(_trackIdToType[id]);
|
||||
: PluginManager.Current.CreateInstance<TResolved>(_id2type[id]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates the ids -> Type dictionary to allow us to instantiate a type by Id since these legacy types doesn't contain any metadata
|
||||
/// Populates the identifiers-to-types dictionnary.
|
||||
/// </summary>
|
||||
protected void EnsureIdsAreTracked()
|
||||
/// <remarks>
|
||||
/// <para>This allow us to instantiate a type by ID since these legacy types doesn't contain any metadata.</para>
|
||||
/// <para>We instanciate all types once to get their unique identifier, then build the dictionary so that
|
||||
/// when GetById is called, we can instanciate a single object.</para>
|
||||
/// </remarks>
|
||||
protected void EnsureIsInitialized()
|
||||
{
|
||||
using (var l = new UpgradeableReadLock(_lock))
|
||||
{
|
||||
if (_trackIdToType == null)
|
||||
if (_id2type == null)
|
||||
{
|
||||
l.UpgradeToWriteLock();
|
||||
_trackIdToType = new ConcurrentDictionary<Guid, Type>();
|
||||
foreach (var v in Values)
|
||||
|
||||
_id2type = new ConcurrentDictionary<Guid, Type>();
|
||||
foreach (var value in Values)
|
||||
{
|
||||
_trackIdToType.TryAdd(GetUniqueIdentifier(v), v.GetType());
|
||||
_id2type.TryAdd(GetUniqueIdentifier(value), value.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user