Core.ObjectsResolution - refactor, cleanup, sanitize, ensure we properly freeze

This commit is contained in:
Stephan
2013-01-16 13:31:04 -01:00
parent bfd8e96f71
commit 01b4e8d59c
29 changed files with 151 additions and 120 deletions

View File

@@ -17,6 +17,7 @@ namespace Umbraco.Core.ObjectResolution
{
private IEnumerable<TResolved> _applicationInstances = null;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly string _httpContextKey;
private readonly List<Type> _instanceTypes = new List<Type>();
private int _defaultPluginWeight = 10;
@@ -41,6 +42,8 @@ namespace Umbraco.Core.ObjectResolution
}
LifetimeScope = scope;
if (scope == ObjectLifetimeScope.HttpRequest)
_httpContextKey = this.GetType().FullName;
_instanceTypes = new List<Type>();
}
@@ -56,6 +59,7 @@ namespace Umbraco.Core.ObjectResolution
if (httpContext == null)
throw new ArgumentNullException("httpContext");
LifetimeScope = ObjectLifetimeScope.HttpRequest;
_httpContextKey = this.GetType().FullName;
CurrentHttpContext = httpContext;
_instanceTypes = new List<Type>();
}
@@ -155,10 +159,10 @@ namespace Umbraco.Core.ObjectResolution
protected IEnumerable<TResolved> Values
{
get
{
// cannot return values unless resolution is frozen, or we can
if (!CanResolveBeforeFrozen && !Resolution.IsFrozen)
throw new InvalidOperationException("Values cannot be returned until resolution is frozen");
{
// ensure we can
if (!CanResolveBeforeFrozen)
Resolution.EnsureIsFrozen();
// note: we apply .ToArray() to the output of CreateInstance() because that is an IEnumerable that
// comes from the PluginManager we want to be _sure_ that it's not a Linq of some sort, but the
@@ -168,16 +172,15 @@ namespace Umbraco.Core.ObjectResolution
{
case ObjectLifetimeScope.HttpRequest:
// create new instances per HttpContext
var key = this.GetType().FullName; // use full type name as key
using (var l = new UpgradeableReadLock(_lock))
{
// create if not already there
if (CurrentHttpContext.Items[key] == null)
if (CurrentHttpContext.Items[_httpContextKey] == null)
{
l.UpgradeToWriteLock();
CurrentHttpContext.Items[key] = CreateInstances().ToArray();
CurrentHttpContext.Items[_httpContextKey] = CreateInstances().ToArray();
}
return (List<TResolved>)CurrentHttpContext.Items[key];
return (List<TResolved>)CurrentHttpContext.Items[_httpContextKey];
}
case ObjectLifetimeScope.Application:
@@ -210,11 +213,13 @@ namespace Umbraco.Core.ObjectResolution
return PluginManager.Current.CreateInstances<TResolved>(InstanceTypes);
}
#region Types collection manipulation
/// <summary>
/// Ensures that a type is a valid type for the resolver.
/// </summary>
/// <param name="value">The type to test.</param>
/// <exception cref="InvalidOperationException"> the type is not a valid type for the resolver.</exception>
/// <exception cref="InvalidOperationException">the type is not a valid type for the resolver.</exception>
protected void EnsureCorrectType(Type value)
{
if (!TypeHelper.IsTypeAssignableFrom<TResolved>(value))
@@ -222,8 +227,6 @@ namespace Umbraco.Core.ObjectResolution
"Type {0} is not an acceptable type for resolver {1}.", value.FullName, this.GetType().FullName));
}
#region Types collection manipulation
/// <summary>
/// Removes a type.
/// </summary>
@@ -233,8 +236,8 @@ namespace Umbraco.Core.ObjectResolution
public virtual void RemoveType(Type value)
{
EnsureRemoveSupport();
EnsureResolutionNotFrozen();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
@@ -265,8 +268,8 @@ namespace Umbraco.Core.ObjectResolution
protected void AddTypes(IEnumerable<Type> types)
{
EnsureAddSupport();
EnsureResolutionNotFrozen();
using (Resolution.Configuration)
using (new WriteLock(_lock))
{
foreach(var t in types)
@@ -292,8 +295,8 @@ namespace Umbraco.Core.ObjectResolution
public virtual void AddType(Type value)
{
EnsureAddSupport();
EnsureResolutionNotFrozen();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
@@ -327,8 +330,8 @@ namespace Umbraco.Core.ObjectResolution
public virtual void Clear()
{
EnsureClearSupport();
EnsureResolutionNotFrozen();
using (Resolution.Configuration)
using (new WriteLock(_lock))
{
_instanceTypes.Clear();
@@ -346,8 +349,8 @@ namespace Umbraco.Core.ObjectResolution
public virtual void InsertType(int index, Type value)
{
EnsureInsertSupport();
EnsureResolutionNotFrozen();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
@@ -373,6 +376,7 @@ namespace Umbraco.Core.ObjectResolution
InsertType(index, typeof(T));
}
/// <summary>
/// Inserts a type before a specified, already existing type.
/// </summary>
/// <param name="existingType">The existing type before which to insert.</param>
@@ -383,8 +387,8 @@ namespace Umbraco.Core.ObjectResolution
public virtual void InsertTypeBefore(Type existingType, Type value)
{
EnsureInsertSupport();
EnsureResolutionNotFrozen();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(existingType);
@@ -452,15 +456,6 @@ namespace Umbraco.Core.ObjectResolution
{
return new WriteLock(_lock);
}
/// <summary>
/// Throws an exception if resolution is frozen
/// </summary>
protected void EnsureResolutionNotFrozen()
{
if (Resolution.IsFrozen)
throw new InvalidOperationException("The type list cannot be modified after resolution has been frozen");
}
/// <summary>
/// Throws an exception if this does not support Remove