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:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Logging;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.ObjectResolution
|
||||
@@ -18,11 +19,13 @@ namespace Umbraco.Core.ObjectResolution
|
||||
private readonly LegacyStartupHandlerResolver _legacyResolver;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="applicationEventHandlers"></param>
|
||||
internal ApplicationEventsResolver(IEnumerable<Type> applicationEventHandlers)
|
||||
: base(applicationEventHandlers)
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="applicationEventHandlers"></param>
|
||||
/// <param name="serviceProvider"></param>
|
||||
internal ApplicationEventsResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable<Type> applicationEventHandlers)
|
||||
: base(serviceProvider, logger, applicationEventHandlers)
|
||||
{
|
||||
//create the legacy resolver and only include the legacy types
|
||||
_legacyResolver = new LegacyStartupHandlerResolver(
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
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,98 +16,133 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <para>This is a special case resolver for when types get lazily resolved in order to resolve the actual types. This is useful
|
||||
/// for when there is some processing overhead (i.e. Type finding in assemblies) to return the Types used to instantiate the instances.
|
||||
/// In some these cases we don't want to have to type-find during application startup, only when we need to resolve the instances.</para>
|
||||
/// <para>Important notes about this resolver: it does not support Insert or Remove and therefore does not support any ordering unless
|
||||
/// <para>Important notes about this resolver: it does not support Insert or Remove and therefore does not support any ordering unless
|
||||
/// the types are marked with the WeightedPluginAttribute.</para>
|
||||
/// </remarks>
|
||||
/// </remarks>
|
||||
public abstract class LazyManyObjectsResolverBase<TResolver, TResolved> : ManyObjectsResolverBase<TResolver, TResolved>
|
||||
where TResolved : class
|
||||
where TResolved : class
|
||||
where TResolver : ResolverBase
|
||||
{
|
||||
#region Constructors
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LazyManyObjectsResolverBase{TResolver, TResolved}"/> class with an empty list of objects,
|
||||
/// with creation of objects based on an HttpRequest lifetime scope.
|
||||
/// 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="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 LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: base(serviceProvider, logger, scope)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use ctor specifying IServiceProvider instead")]
|
||||
protected LazyManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: base(scope)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LazyManyObjectsResolverBase{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>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use ctor specifying IServiceProvider instead")]
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext)
|
||||
: base(httpContext)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LazyManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list
|
||||
/// <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>
|
||||
protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable<Lazy<Type>> lazyTypeList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(serviceProvider, logger, scope)
|
||||
{
|
||||
AddTypes(lazyTypeList);
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use ctor specifying IServiceProvider instead")]
|
||||
protected LazyManyObjectsResolverBase(IEnumerable<Lazy<Type>> lazyTypeList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(scope)
|
||||
{
|
||||
AddTypes(lazyTypeList);
|
||||
}
|
||||
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, lazyTypeList, scope)
|
||||
{
|
||||
}
|
||||
|
||||
protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> typeListProducerList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(serviceProvider, logger, scope)
|
||||
{
|
||||
_typeListProducerList.Add(typeListProducerList);
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use ctor specifying IServiceProvider instead")]
|
||||
protected LazyManyObjectsResolverBase(Func<IEnumerable<Type>> typeListProducerList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, typeListProducerList, scope)
|
||||
{
|
||||
}
|
||||
|
||||
protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext, IEnumerable<Lazy<Type>> lazyTypeList)
|
||||
: this(serviceProvider, logger, httpContext)
|
||||
{
|
||||
AddTypes(lazyTypeList);
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use ctor specifying IServiceProvider instead")]
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Lazy<Type>> lazyTypeList)
|
||||
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext, lazyTypeList)
|
||||
{
|
||||
}
|
||||
|
||||
protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext, Func<IEnumerable<Type>> typeListProducerList)
|
||||
: this(serviceProvider, logger, httpContext)
|
||||
{
|
||||
_typeListProducerList.Add(typeListProducerList);
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use ctor specifying IServiceProvider instead")]
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, Func<IEnumerable<Type>> typeListProducerList)
|
||||
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext, typeListProducerList)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly List<Lazy<Type>> _lazyTypeList = new List<Lazy<Type>>();
|
||||
private readonly List<Func<IEnumerable<Type>>> _typeListProducerList = new List<Func<IEnumerable<Type>>>();
|
||||
private readonly List<Type> _excludedTypesList = new List<Type>();
|
||||
private Lazy<List<Type>> _resolvedTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LazyManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list
|
||||
/// of functions producing types, and an optional lifetime scope.
|
||||
/// 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="typeListProducerList">The list of functions producing types.</param>
|
||||
/// <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 LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext)
|
||||
: base(serviceProvider, 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="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 LazyManyObjectsResolverBase(Func<IEnumerable<Type>> typeListProducerList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(scope)
|
||||
{
|
||||
_typeListProducerList.Add(typeListProducerList);
|
||||
}
|
||||
protected LazyManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: base(serviceProvider, logger, value, scope)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LazyManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of
|
||||
/// lazy object types, with creation of objects based on an HttpRequest lifetime scope.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The HttpContextBase corresponding to the HttpRequest.</param>
|
||||
/// <param name="lazyTypeList">The list of lazy object types.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Lazy<Type>> lazyTypeList)
|
||||
: this(httpContext)
|
||||
{
|
||||
AddTypes(lazyTypeList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LazyManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of
|
||||
/// functions producing types, with creation of objects based on an HttpRequest lifetime scope.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The HttpContextBase corresponding to the HttpRequest.</param>
|
||||
/// <param name="typeListProducerList">The list of functions producing types.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, Func<IEnumerable<Type>> typeListProducerList)
|
||||
: this(httpContext)
|
||||
{
|
||||
_typeListProducerList.Add(typeListProducerList);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly List<Lazy<Type>> _lazyTypeList = new List<Lazy<Type>>();
|
||||
private readonly List<Func<IEnumerable<Type>>> _typeListProducerList = new List<Func<IEnumerable<Type>>>();
|
||||
private readonly List<Type> _excludedTypesList = new List<Type>();
|
||||
private Lazy<List<Type>> _resolvedTypes = null;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
_resolvedTypes = new Lazy<List<Type>>(() =>
|
||||
@@ -129,23 +165,23 @@ namespace Umbraco.Core.ObjectResolution
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the resolver has resolved types to create instances from.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the resolver has resolved types to create instances from.
|
||||
/// </summary>
|
||||
/// <remarks>To be used in unit tests.</remarks>
|
||||
public bool HasResolvedTypes
|
||||
{
|
||||
get { return _resolvedTypes.IsValueCreated; }
|
||||
}
|
||||
public bool HasResolvedTypes
|
||||
{
|
||||
get { return _resolvedTypes.IsValueCreated; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of types to create instances from.
|
||||
/// </summary>
|
||||
/// <remarks>When called, will get the types from the lazy list.</remarks>
|
||||
protected override IEnumerable<Type> InstanceTypes
|
||||
{
|
||||
get { return _resolvedTypes.Value; }
|
||||
}
|
||||
{
|
||||
get { return _resolvedTypes.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that type is valid and not a duplicate
|
||||
@@ -154,15 +190,15 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <param name="list"></param>
|
||||
/// <param name="type"></param>
|
||||
private void AddValidAndNoDuplicate(List<Type> list, Type type)
|
||||
{
|
||||
{
|
||||
EnsureCorrectType(type);
|
||||
if (list.Contains(type))
|
||||
{
|
||||
{
|
||||
throw new InvalidOperationException(string.Format(
|
||||
"Type {0} is already in the collection of types.", type.FullName));
|
||||
}
|
||||
list.Add(type);
|
||||
}
|
||||
}
|
||||
|
||||
#region Types collection manipulation
|
||||
|
||||
@@ -179,86 +215,86 @@ namespace Umbraco.Core.ObjectResolution
|
||||
|
||||
/// <summary>
|
||||
/// Lazily adds types from lazy types.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
/// <param name="types">The lazy types, to add.</param>
|
||||
protected void AddTypes(IEnumerable<Lazy<Type>> types)
|
||||
{
|
||||
EnsureSupportsAdd();
|
||||
protected void AddTypes(IEnumerable<Lazy<Type>> types)
|
||||
{
|
||||
EnsureSupportsAdd();
|
||||
|
||||
using (Resolution.Configuration)
|
||||
using (GetWriteLock())
|
||||
{
|
||||
foreach (var t in types)
|
||||
{
|
||||
_lazyTypeList.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
foreach (var t in types)
|
||||
{
|
||||
_lazyTypeList.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Lazily adds types from a function producing types.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
/// <param name="typeListProducer">The functions producing types, to add.</param>
|
||||
public void AddTypeListDelegate(Func<IEnumerable<Type>> typeListProducer)
|
||||
{
|
||||
{
|
||||
EnsureSupportsAdd();
|
||||
|
||||
using (Resolution.Configuration)
|
||||
using (GetWriteLock())
|
||||
{
|
||||
{
|
||||
_typeListProducerList.Add(typeListProducer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Lazily adds a type from a lazy type.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
/// <param name="value">The lazy type, to add.</param>
|
||||
public void AddType(Lazy<Type> value)
|
||||
{
|
||||
public void AddType(Lazy<Type> value)
|
||||
{
|
||||
EnsureSupportsAdd();
|
||||
|
||||
using (Resolution.Configuration)
|
||||
using (GetWriteLock())
|
||||
{
|
||||
_lazyTypeList.Add(value);
|
||||
}
|
||||
}
|
||||
{
|
||||
_lazyTypeList.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Lazily adds a type from an actual type.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
/// <param name="value">The actual type, to add.</param>
|
||||
/// <remarks>The type is converted to a lazy type.</remarks>
|
||||
public override void AddType(Type value)
|
||||
{
|
||||
AddType(new Lazy<Type>(() => value));
|
||||
}
|
||||
public override void AddType(Type value)
|
||||
{
|
||||
AddType(new Lazy<Type>(() => value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all lazy types
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
EnsureSupportsClear();
|
||||
/// <summary>
|
||||
/// Clears all lazy types
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
EnsureSupportsClear();
|
||||
|
||||
using (Resolution.Configuration)
|
||||
using (GetWriteLock())
|
||||
{
|
||||
_lazyTypeList.Clear();
|
||||
}
|
||||
}
|
||||
{
|
||||
_lazyTypeList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Types collection manipulation support
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Gets a <c>false</c> value indicating that the resolver does NOT support inserting types.
|
||||
/// </summary>
|
||||
protected override bool SupportsInsert
|
||||
{
|
||||
get { return false; }
|
||||
/// </summary>
|
||||
protected override bool SupportsInsert
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
@@ -22,21 +22,23 @@ namespace Umbraco.Core.ObjectResolution
|
||||
where TResolver : ResolverBase
|
||||
{
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
private ConcurrentDictionary<Guid, Type> _id2type;
|
||||
private ConcurrentDictionary<Guid, Type> _id2Type;
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LegacyTransientObjectsResolver{TResolver, TResolved}"/> class with an initial list of object types.
|
||||
/// </summary>
|
||||
/// <param name="value">A function returning the list of object types.</param>
|
||||
/// <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>
|
||||
protected LegacyTransientObjectsResolver(Func<IEnumerable<Type>> value)
|
||||
: base(value, ObjectLifetimeScope.Transient) // new objects every time
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LegacyTransientObjectsResolver{TResolver, TResolved}"/> class with an initial list of object types.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="value">A function returning the list of object types.</param>
|
||||
/// <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>
|
||||
protected LegacyTransientObjectsResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> value)
|
||||
: base(serviceProvider, logger, value, ObjectLifetimeScope.Transient) // new objects every time
|
||||
{ }
|
||||
#endregion
|
||||
|
||||
@@ -55,9 +57,9 @@ namespace Umbraco.Core.ObjectResolution
|
||||
public TResolved GetById(Guid id)
|
||||
{
|
||||
EnsureIsInitialized();
|
||||
return !_id2type.ContainsKey(id)
|
||||
return _id2Type.ContainsKey(id) == false
|
||||
? null
|
||||
: PluginManager.Current.CreateInstance<TResolved>(_id2type[id]);
|
||||
: ServiceProvider.GetService(_id2Type[id]) as TResolved;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -72,14 +74,14 @@ namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
using (var l = new UpgradeableReadLock(_lock))
|
||||
{
|
||||
if (_id2type == null)
|
||||
if (_id2Type == null)
|
||||
{
|
||||
l.UpgradeToWriteLock();
|
||||
|
||||
_id2type = new ConcurrentDictionary<Guid, Type>();
|
||||
_id2Type = new ConcurrentDictionary<Guid, Type>();
|
||||
foreach (var value in Values)
|
||||
{
|
||||
_id2type.TryAdd(GetUniqueIdentifier(value), value.GetType());
|
||||
_id2Type.TryAdd(GetUniqueIdentifier(value), value.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user