Rename namespace from Umbraco.Core.Resolving to Umbraco.Core.ObjectResolution
This commit is contained in:
236
src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs
Normal file
236
src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
internal abstract class ManyObjectsResolverBase<TResolver, TResolved> : ResolverBase<TResolver>
|
||||
where TResolved : class
|
||||
where TResolver : class
|
||||
{
|
||||
private List<TResolved> _applicationInstances = null;
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an empty list of objects.
|
||||
/// </summary>
|
||||
/// <param name="scope">The lifetime scope of instantiated objects, default is per Application</param>
|
||||
protected ManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
{
|
||||
if (scope == ObjectLifetimeScope.HttpRequest)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
{
|
||||
throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null");
|
||||
}
|
||||
CurrentHttpContext = new HttpContextWrapper(HttpContext.Current);
|
||||
}
|
||||
|
||||
LifetimeScope = scope;
|
||||
InstanceTypes = new List<Type>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an empty list of objects.
|
||||
/// with creation of objects based on an HttpRequest lifetime scope.
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
protected ManyObjectsResolverBase(HttpContextBase httpContext)
|
||||
{
|
||||
LifetimeScope = ObjectLifetimeScope.HttpRequest;
|
||||
CurrentHttpContext = httpContext;
|
||||
InstanceTypes = new List<Type>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of objects.
|
||||
/// </summary>
|
||||
/// <param name="value">The list of objects.</param>
|
||||
/// <param name="scope">If set to true will resolve singleton objects which will be created once for the lifetime of the application</param>
|
||||
protected ManyObjectsResolverBase(IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(scope)
|
||||
{
|
||||
InstanceTypes = new List<Type>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of objects
|
||||
/// with creation of objects based on an HttpRequest lifetime scope.
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <param name="value"></param>
|
||||
protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Type> value)
|
||||
: this(httpContext)
|
||||
{
|
||||
InstanceTypes = new List<Type>(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of Types registered that instances will be created from
|
||||
/// </summary>
|
||||
protected List<Type> InstanceTypes { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Current HttpContextBase used to construct this object if one exists.
|
||||
/// If one exists then the LifetimeScope will be ObjectLifetimeScope.HttpRequest
|
||||
/// </summary>
|
||||
protected HttpContextBase CurrentHttpContext { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the ObjectLifetimeScope for created objects
|
||||
/// </summary>
|
||||
protected ObjectLifetimeScope LifetimeScope { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of new object instances.
|
||||
/// </summary>
|
||||
protected IEnumerable<TResolved> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
//We cannot return values unless resolution is locked
|
||||
if (!Resolution.IsFrozen)
|
||||
throw new InvalidOperationException("Values cannot be returned until Resolution is frozen");
|
||||
|
||||
switch (LifetimeScope)
|
||||
{
|
||||
case ObjectLifetimeScope.HttpRequest:
|
||||
//create new instances per HttpContext, this means we'll lazily create them and once created, cache them in the HttpContext
|
||||
//create new instances per application, this means we'll lazily create them and once created, cache them
|
||||
using (var l = new UpgradeableReadLock(_lock))
|
||||
{
|
||||
//check if the items contain the key (based on the full type name)
|
||||
if (CurrentHttpContext.Items[this.GetType().FullName] == null)
|
||||
{
|
||||
l.UpgradeToWriteLock();
|
||||
//add the items to the context items (based on full type name)
|
||||
CurrentHttpContext.Items[this.GetType().FullName] = new List<TResolved>(CreateInstances());
|
||||
}
|
||||
return (List<TResolved>)CurrentHttpContext.Items[this.GetType().FullName];
|
||||
}
|
||||
case ObjectLifetimeScope.Application:
|
||||
//create new instances per application, this means we'll lazily create them and once created, cache them
|
||||
using(var l = new UpgradeableReadLock(_lock))
|
||||
{
|
||||
if (_applicationInstances == null)
|
||||
{
|
||||
l.UpgradeToWriteLock();
|
||||
_applicationInstances = new List<TResolved>(CreateInstances());
|
||||
}
|
||||
return _applicationInstances;
|
||||
}
|
||||
case ObjectLifetimeScope.Transient:
|
||||
default:
|
||||
//create new instances each time
|
||||
return CreateInstances();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<TResolved> CreateInstances()
|
||||
{
|
||||
return PluginManager.Current.CreateInstances<TResolved>(InstanceTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to remove.</param>
|
||||
public void RemoveType(Type value)
|
||||
{
|
||||
EnsureCorrectType(value);
|
||||
using (new WriteLock(_lock))
|
||||
{
|
||||
InstanceTypes.Remove(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public void RemoveType<T>()
|
||||
{
|
||||
RemoveType(typeof (T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Type to the end of the list.
|
||||
/// </summary>
|
||||
/// <param name="value">The object to be added.</param>
|
||||
public void AddType(Type value)
|
||||
{
|
||||
EnsureCorrectType(value);
|
||||
using (var l = new UpgradeableReadLock(_lock))
|
||||
{
|
||||
if (InstanceTypes.Contains(value))
|
||||
{
|
||||
throw new InvalidOperationException("The Type " + value + " already exists in the collection");
|
||||
};
|
||||
|
||||
l.UpgradeToWriteLock();
|
||||
InstanceTypes.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Type to the end of the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public void AddType<T>()
|
||||
{
|
||||
AddType(typeof (T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the list.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
using (new WriteLock(_lock))
|
||||
{
|
||||
InstanceTypes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a Type at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which the object should be inserted.</param>
|
||||
/// <param name="value">The object to insert.</param>
|
||||
public void InsertType(int index, Type value)
|
||||
{
|
||||
EnsureCorrectType(value);
|
||||
using (var l = new UpgradeableReadLock(_lock))
|
||||
{
|
||||
if (InstanceTypes.Contains(value))
|
||||
{
|
||||
throw new InvalidOperationException("The Type " + value + " already exists in the collection");
|
||||
};
|
||||
|
||||
l.UpgradeToWriteLock();
|
||||
InstanceTypes.Insert(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a Type at the specified index.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="index"></param>
|
||||
public void InsertType<T>(int index)
|
||||
{
|
||||
InsertType(index, typeof (T));
|
||||
}
|
||||
|
||||
private void EnsureCorrectType(Type t)
|
||||
{
|
||||
if (!TypeHelper.IsTypeAssignableFrom<TResolved>(t))
|
||||
throw new InvalidOperationException("The resolver " + this.GetType() + " can only accept types of " + typeof(TResolved) + ". The Type passed in to this method is " + t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user