Decoupling more things, mostly to do with the PluginManager and logging which now requires an IServiceProvider so have created a simple instance of that.

This commit is contained in:
Shannon
2015-01-16 15:47:44 +11:00
parent 8f100a7e9f
commit 1cb0cd296c
77 changed files with 1105 additions and 819 deletions

View File

@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Web;
using Umbraco.Core.Logging;
namespace Umbraco.Core.ObjectResolution
{
@@ -15,75 +17,111 @@ namespace Umbraco.Core.ObjectResolution
where TResolved : class
where TResolver : ResolverBase
{
private Lazy<IEnumerable<TResolved>> _applicationInstances = null;
private Lazy<IEnumerable<TResolved>> _applicationInstances;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly string _httpContextKey;
private readonly List<Type> _instanceTypes = new List<Type>();
private IEnumerable<TResolved> _sortedValues = null;
private IEnumerable<TResolved> _sortedValues;
private int _defaultPluginWeight = 10;
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an empty list of objects,
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an empty list of objects,
/// and an optional lifetime scope.
/// </summary>
/// <param name="scope">The lifetime scope of instantiated objects, default is per Application.</param>
/// <remarks>If <paramref name="scope"/> is per HttpRequest then there must be a current HttpContext.</remarks>
/// <exception cref="InvalidOperationException"><paramref name="scope"/> is per HttpRequest but the current HttpContext is null.</exception>
/// </summary>
/// <param name="serviceProvider"></param>
/// <param name="logger"></param>
/// <param name="scope">The lifetime scope of instantiated objects, default is per Application.</param>
/// <remarks>If <paramref name="scope"/> is per HttpRequest then there must be a current HttpContext.</remarks>
/// <exception cref="InvalidOperationException"><paramref name="scope"/> is per HttpRequest but the current HttpContext is null.</exception>
protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
{
if (serviceProvider == null) throw new ArgumentNullException("serviceProvider");
if (logger == null) throw new ArgumentNullException("logger");
CanResolveBeforeFrozen = false;
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);
}
ServiceProvider = serviceProvider;
Logger = logger;
LifetimeScope = scope;
if (scope == ObjectLifetimeScope.HttpRequest)
_httpContextKey = GetType().FullName;
_instanceTypes = new List<Type>();
InitializeAppInstances();
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use ctor specifying IServiceProvider instead")]
protected ManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, scope)
{
CanResolveBeforeFrozen = false;
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;
if (scope == ObjectLifetimeScope.HttpRequest)
_httpContextKey = this.GetType().FullName;
_instanceTypes = new List<Type>();
InitializeAppInstances();
}
/// <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">The HttpContextBase corresponding to the HttpRequest.</param>
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
protected ManyObjectsResolverBase(HttpContextBase httpContext)
/// <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="serviceProvider"></param>
/// <param name="logger"></param>
/// <param name="httpContext">The HttpContextBase corresponding to the HttpRequest.</param>
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext)
{
CanResolveBeforeFrozen = false;
if (httpContext == null)
throw new ArgumentNullException("httpContext");
if (serviceProvider == null) throw new ArgumentNullException("serviceProvider");
if (httpContext == null) throw new ArgumentNullException("httpContext");
CanResolveBeforeFrozen = false;
Logger = logger;
LifetimeScope = ObjectLifetimeScope.HttpRequest;
_httpContextKey = this.GetType().FullName;
CurrentHttpContext = httpContext;
_httpContextKey = GetType().FullName;
ServiceProvider = serviceProvider;
CurrentHttpContext = httpContext;
_instanceTypes = new List<Type>();
InitializeAppInstances();
}
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of object types,
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use ctor specifying IServiceProvider instead")]
protected ManyObjectsResolverBase(HttpContextBase httpContext)
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of object types,
/// and an optional lifetime scope.
/// </summary>
/// <param name="value">The list of object types.</param>
/// <param name="scope">The lifetime scope of instantiated objects, default is per Application.</param>
/// <remarks>If <paramref name="scope"/> is per HttpRequest then there must be a current HttpContext.</remarks>
/// <exception cref="InvalidOperationException"><paramref name="scope"/> is per HttpRequest but the current HttpContext is null.</exception>
protected ManyObjectsResolverBase(IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(scope)
/// </summary>
/// <param name="serviceProvider"></param>
/// <param name="logger"></param>
/// <param name="value">The list of object types.</param>
/// <param name="scope">The lifetime scope of instantiated objects, default is per Application.</param>
/// <remarks>If <paramref name="scope"/> is per HttpRequest then there must be a current HttpContext.</remarks>
/// <exception cref="InvalidOperationException"><paramref name="scope"/> is per HttpRequest but the current HttpContext is null.</exception>
protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(serviceProvider, logger, scope)
{
_instanceTypes = value.ToList();
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use ctor specifying IServiceProvider instead")]
protected ManyObjectsResolverBase(IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, value, scope)
{
}
/// <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.
@@ -91,8 +129,9 @@ namespace Umbraco.Core.ObjectResolution
/// <param name="httpContext">The HttpContextBase corresponding to the HttpRequest.</param>
/// <param name="value">The list of object types.</param>
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Type> value)
: this(httpContext)
[Obsolete("Use ctor specifying IServiceProvider instead")]
protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Type> value)
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext)
{
_instanceTypes = value.ToList();
}
@@ -123,7 +162,14 @@ namespace Umbraco.Core.ObjectResolution
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
protected HttpContextBase CurrentHttpContext { get; private set; }
/// <summary>
/// <summary>
/// Returns the service provider used to instantiate objects
/// </summary>
public IServiceProvider ServiceProvider { get; private set; }
public ILogger Logger { get; private set; }
/// <summary>
/// Gets or sets the lifetime scope of resolved objects.
/// </summary>
protected ObjectLifetimeScope LifetimeScope { get; private set; }
@@ -214,7 +260,7 @@ namespace Umbraco.Core.ObjectResolution
/// <returns>A list of objects of type <typeparamref name="TResolved"/>.</returns>
protected virtual IEnumerable<TResolved> CreateInstances()
{
return PluginManager.Current.CreateInstances<TResolved>(InstanceTypes);
return ServiceProvider.CreateInstances<TResolved>(InstanceTypes, Logger);
}
#region Types collection manipulation
@@ -423,7 +469,7 @@ namespace Umbraco.Core.ObjectResolution
{
EnsureCorrectType(existingType);
EnsureCorrectType(value);
if (!_instanceTypes.Contains(existingType))
if (_instanceTypes.Contains(existingType) == false)
{
throw new InvalidOperationException(string.Format(
"Type {0} is not in the collection of types.", existingType.FullName));
@@ -514,9 +560,9 @@ namespace Umbraco.Core.ObjectResolution
/// <exception cref="InvalidOperationException">the type is not a valid type for the resolver.</exception>
protected virtual void EnsureCorrectType(Type value)
{
if (!TypeHelper.IsTypeAssignableFrom<TResolved>(value))
if (TypeHelper.IsTypeAssignableFrom<TResolved>(value) == false)
throw new InvalidOperationException(string.Format(
"Type {0} is not an acceptable type for resolver {1}.", value.FullName, this.GetType().FullName));
"Type {0} is not an acceptable type for resolver {1}.", value.FullName, GetType().FullName));
}
#endregion
@@ -529,7 +575,7 @@ namespace Umbraco.Core.ObjectResolution
/// <exception cref="InvalidOperationException">The resolver does not support removing types.</exception>
protected void EnsureSupportsRemove()
{
if (!SupportsRemove)
if (SupportsRemove == false)
throw new InvalidOperationException("This resolver does not support removing types");
}
@@ -538,7 +584,7 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <exception cref="InvalidOperationException">The resolver does not support clearing types.</exception>
protected void EnsureSupportsClear() {
if (!SupportsClear)
if (SupportsClear == false)
throw new InvalidOperationException("This resolver does not support clearing types");
}
@@ -548,7 +594,7 @@ namespace Umbraco.Core.ObjectResolution
/// <exception cref="InvalidOperationException">The resolver does not support adding types.</exception>
protected void EnsureSupportsAdd()
{
if (!SupportsAdd)
if (SupportsAdd == false)
throw new InvalidOperationException("This resolver does not support adding new types");
}
@@ -558,7 +604,7 @@ namespace Umbraco.Core.ObjectResolution
/// <exception cref="InvalidOperationException">The resolver does not support inserting types.</exception>
protected void EnsureSupportsInsert()
{
if (!SupportsInsert)
if (SupportsInsert == false)
throw new InvalidOperationException("This resolver does not support inserting new types");
}