2012-08-01 10:05:39 +06:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Collections.Generic;
|
2012-10-13 10:59:21 +05:00
|
|
|
using System.Linq;
|
2012-08-01 10:05:39 +06:00
|
|
|
using System.Threading;
|
|
|
|
|
|
2012-08-10 13:18:13 +06:00
|
|
|
namespace Umbraco.Core.ObjectResolution
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
|
|
|
|
/// <summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// The base class for old legacy factories such as the DataTypeFactory or CacheResolverFactory.
|
2012-08-01 10:05:39 +06:00
|
|
|
/// </summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// <typeparam name="TResolver">The type of the concrete resolver class.</typeparam>
|
|
|
|
|
/// <typeparam name="TResolved">The type of the resolved objects.</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>
|
2013-01-23 18:40:40 +03:00
|
|
|
internal abstract class LegacyTransientObjectsResolver<TResolver, TResolved> : LazyManyObjectsResolverBase<TResolver, TResolved>
|
2012-08-01 22:06:15 +06:00
|
|
|
where TResolved : class
|
|
|
|
|
where TResolver : class
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
2013-01-16 13:31:04 -01:00
|
|
|
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
|
|
|
|
private ConcurrentDictionary<Guid, Type> _id2type;
|
|
|
|
|
|
2012-08-01 10:05:39 +06:00
|
|
|
#region Constructors
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2013-01-23 16:44:38 -01:00
|
|
|
/// Initializes a new instance of the <see cref="LegacyTransientObjectsResolver{TResolver, TResolved}"/> class with an initial list of object types.
|
2012-08-01 10:05:39 +06:00
|
|
|
/// </summary>
|
2013-01-23 16:44:38 -01:00
|
|
|
/// <param name="value">A function returning the list of object types.</param>
|
2012-08-01 10:05:39 +06:00
|
|
|
/// <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>
|
2013-01-23 16:44:38 -01:00
|
|
|
protected LegacyTransientObjectsResolver(Func<IEnumerable<Type>> value)
|
|
|
|
|
: base(value, ObjectLifetimeScope.Transient) // new objects every time
|
|
|
|
|
{ }
|
2012-08-01 10:05:39 +06:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// Returns the unique identifier of the type of a specified object.
|
2012-08-01 10:05:39 +06:00
|
|
|
/// </summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// <param name="value">The object.</param>
|
|
|
|
|
/// <returns>The unique identifier of the type of <paramref name="value"/>.</returns>
|
|
|
|
|
protected abstract Guid GetUniqueIdentifier(TResolved value);
|
2012-08-01 10:05:39 +06:00
|
|
|
|
|
|
|
|
/// <summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// Returns a new instance for the type identified by its unique type identifier.
|
2012-08-01 10:05:39 +06:00
|
|
|
/// </summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// <param name="id">The type identifier.</param>
|
|
|
|
|
/// <returns>The value of the type uniquely identified by <paramref name="id"/>.</returns>
|
2012-08-01 22:06:15 +06:00
|
|
|
public TResolved GetById(Guid id)
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
2013-01-16 13:31:04 -01:00
|
|
|
EnsureIsInitialized();
|
|
|
|
|
return !_id2type.ContainsKey(id)
|
2012-08-01 10:05:39 +06:00
|
|
|
? null
|
2013-01-16 13:31:04 -01:00
|
|
|
: PluginManager.Current.CreateInstance<TResolved>(_id2type[id]);
|
2012-08-01 10:05:39 +06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// Populates the identifiers-to-types dictionnary.
|
2012-08-01 10:05:39 +06:00
|
|
|
/// </summary>
|
2013-01-16 13:31:04 -01:00
|
|
|
/// <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()
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
|
|
|
|
using (var l = new UpgradeableReadLock(_lock))
|
|
|
|
|
{
|
2013-01-16 13:31:04 -01:00
|
|
|
if (_id2type == null)
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
|
|
|
|
l.UpgradeToWriteLock();
|
2013-01-16 13:31:04 -01:00
|
|
|
|
|
|
|
|
_id2type = new ConcurrentDictionary<Guid, Type>();
|
|
|
|
|
foreach (var value in Values)
|
2012-08-01 10:05:39 +06:00
|
|
|
{
|
2013-01-16 13:31:04 -01:00
|
|
|
_id2type.TryAdd(GetUniqueIdentifier(value), value.GetType());
|
2012-08-01 10:05:39 +06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|