diff --git a/src/Umbraco.Core/DependencyInjection/CollectionBuilderBase.cs b/src/Umbraco.Core/DependencyInjection/CollectionBuilderBase.cs
index 4a8c2ccf8a..b19b220620 100644
--- a/src/Umbraco.Core/DependencyInjection/CollectionBuilderBase.cs
+++ b/src/Umbraco.Core/DependencyInjection/CollectionBuilderBase.cs
@@ -171,5 +171,18 @@ namespace Umbraco.Core.DependencyInjection
if (_collectionCtor == null) throw new InvalidOperationException("Collection auto-creation is not possible.");
return _collectionCtor(CreateItems());
}
+
+ ///
+ /// Gets a value indicating whether the collection contains a type.
+ ///
+ /// The type to look for.
+ /// A value indicating whether the collection contains the type.
+ /// Some builder implementations may use this to expose a public Has{T}() method,
+ /// when it makes sense. Probably does not make sense for lazy builders, for example.
+ protected bool HasBase()
+ where T : TItem
+ {
+ return _types.Contains(typeof (T));
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/DependencyInjection/OrderedCollectionBuilderBase.cs b/src/Umbraco.Core/DependencyInjection/OrderedCollectionBuilderBase.cs
index 96d0a85762..55bf274af9 100644
--- a/src/Umbraco.Core/DependencyInjection/OrderedCollectionBuilderBase.cs
+++ b/src/Umbraco.Core/DependencyInjection/OrderedCollectionBuilderBase.cs
@@ -48,6 +48,9 @@ namespace Umbraco.Core.DependencyInjection
{
foreach (var type in types)
{
+ // would be detected by CollectionBuilderBase when registering, anyways, but let's fail fast
+ if (typeof(TItem).IsAssignableFrom(type) == false)
+ throw new InvalidOperationException($"Cannot register type {type.FullName} as it does not inherit from/implement {typeof(TItem).FullName}.");
if (list.Contains(type)) list.Remove(type);
list.Add(type);
}
@@ -86,15 +89,17 @@ namespace Umbraco.Core.DependencyInjection
/// Inserts a type into the collection.
///
/// The type to insert.
+ /// The optional index.
/// The builder.
- public TBuilder Insert()
+ /// Throws if the index is out of range.
+ public TBuilder Insert(int index = 0)
where T : TItem
{
Configure(types =>
{
var type = typeof (T);
if (types.Contains(type)) types.Remove(type);
- types.Insert(0, type);
+ types.Insert(index, type);
});
return This;
}
@@ -169,5 +174,26 @@ namespace Umbraco.Core.DependencyInjection
});
return This;
}
+
+ ///
+ /// Gets a value indicating whether the collection contains a type.
+ ///
+ /// The type to look for.
+ /// A value indicating whether the collection contains the type.
+ public bool Has()
+ where T : TItem
+ {
+ return HasBase();
+ }
+
+ ///
+ /// Clears all types in the collection.
+ ///
+ /// The buidler.
+ public TBuilder Clear()
+ {
+ Configure(types => types.Clear());
+ return This;
+ }
}
}
diff --git a/src/Umbraco.Core/ObjectResolution/ContainerManyObjectsResolver.cs b/src/Umbraco.Core/ObjectResolution/ContainerManyObjectsResolver.cs
deleted file mode 100644
index 2454a8f2c9..0000000000
--- a/src/Umbraco.Core/ObjectResolution/ContainerManyObjectsResolver.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using LightInject;
-using Umbraco.Core.Logging;
-
-namespace Umbraco.Core.ObjectResolution
-{
- ///
- /// A many objects resolver that uses IoC
- ///
- ///
- ///
- public abstract class ContainerManyObjectsResolver : ManyObjectsResolverBase
- where TResolved : class
- where TResolver : ResolverBase
- {
- private readonly IServiceContainer _container;
-
- //TODO: Get rid of these - pretty sure all tests will still fail with these pass throughs, need to update
- // all tests that use resolvers to use a real container - then update most tests that are not integration tests to not use any resolvers!
- #region Constructors used for test - ONLY so that a container is not required and will just revert to using the normal ManyObjectsResolverBase
- [Obsolete("Used for tests only - should remove")]
- internal ContainerManyObjectsResolver(ILogger logger, IEnumerable types, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- : base(logger, types, scope)
- {
- }
- [Obsolete("Used for tests only - should remove")]
- internal ContainerManyObjectsResolver(IServiceProvider serviceProvider, ILogger logger, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- : base(serviceProvider, logger, scope)
- {
- }
- [Obsolete("Used for tests only - should remove")]
- internal ContainerManyObjectsResolver(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext)
- : base(serviceProvider, logger, httpContext)
- {
- }
- [Obsolete("Used for tests only - should remove")]
- internal ContainerManyObjectsResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- : base(serviceProvider, logger, value, scope)
- {
- }
- #endregion
-
- ///
- /// Constructor for use with IoC
- ///
- ///
- ///
- ///
- ///
- internal ContainerManyObjectsResolver(IServiceContainer container, ILogger logger, IEnumerable types, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- : base(logger, types, scope)
- {
- if (container == null) throw new ArgumentNullException(nameof(container));
- _container = container;
- Resolution.Frozen += Resolution_Frozen;
- }
-
- ///
- /// When resolution is frozen add all the types to the container
- ///
- ///
- ///
- void Resolution_Frozen(object sender, EventArgs e)
- {
- var prefix = GetType().FullName + "_";
- var i = 0;
- foreach (var type in InstanceTypes)
- {
- var name = $"{prefix}{i++:00000}";
- _container.Register(typeof(TResolved), type, name, GetLifetime(LifetimeScope));
- }
- }
-
- ///
- /// Convert the ObjectLifetimeScope to ILifetime
- ///
- ///
- ///
- private static ILifetime GetLifetime(ObjectLifetimeScope scope)
- {
- switch (scope)
- {
- case ObjectLifetimeScope.HttpRequest:
- return new PerRequestLifeTime();
- case ObjectLifetimeScope.Application:
- return new PerContainerLifetime();
- //case ObjectLifetimeScope.Transient:
- default:
- return null;
- }
- }
-
- ///
- /// Creates the instances from IoC
- ///
- /// A list of objects of type .
- protected override IEnumerable CreateInstances()
- {
- //NOTE: we ignore scope because objects are registered under this scope and not build based on the scope.
-
- var prefix = GetType().FullName + "_";
-
- // GetAllInstances could return more than what *this* resolver has registered,
- // and there is no guarantee instances will be in the right order - have to do
- // it differently
-
- var services = _container.AvailableServices
- .Where(x => x.ServiceName.StartsWith(prefix))
- .OrderBy(x => x.ServiceName);
-
- var values = services
- .Select(x => _container.GetInstance(x.ServiceName))
- .ToArray();
-
- return values;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs
deleted file mode 100644
index ca9243bc8a..0000000000
--- a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs
+++ /dev/null
@@ -1,642 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Web;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Plugins;
-
-namespace Umbraco.Core.ObjectResolution
-{
- ///
- /// The base class for all many-objects resolvers.
- ///
- /// The type of the concrete resolver class.
- /// The type of the resolved objects.
- public abstract class ManyObjectsResolverBase : ResolverBase
- where TResolved : class
- where TResolver : ResolverBase
- {
- private Lazy> _applicationInstances;
- private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
- private readonly string _httpContextKey;
- private readonly List _instanceTypes;
- private IEnumerable _sortedValues;
-
- #region Constructors
-
- ///
- /// Hack: This is purely here to allow for the container resolver to be used, we'll need to refactor all of this slowly till we're
- /// happy with the outcome
- ///
- ///
- ///
- ///
- internal ManyObjectsResolverBase(ILogger logger, IEnumerable types, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- {
- if (logger == null) throw new ArgumentNullException(nameof(logger));
- if (types == null) throw new ArgumentNullException(nameof(types));
- CanResolveBeforeFrozen = false;
- _instanceTypes = types.ToList();
- LifetimeScope = scope;
- Logger = logger;
-
- if (scope == ObjectLifetimeScope.Application)
- InitializeAppInstances();
- }
-
- ///
- /// Hack: This is purely here to allow for the lazy container resolver to be used, we'll need to refactor all of this slowly till we're
- /// happy with the outcome
- ///
- ///
- ///
- internal ManyObjectsResolverBase(ILogger logger, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- : this(logger, new List(), scope)
- { }
-
-
- ///
- /// Initializes a new instance of the class with an empty list of objects,
- /// and an optional lifetime scope.
- ///
- ///
- ///
- /// The lifetime scope of instantiated objects, default is per Application.
- /// If is per HttpRequest then there must be a current HttpContext.
- /// is per HttpRequest but the current HttpContext is null.
- protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- {
- if (serviceProvider == null) throw new ArgumentNullException(nameof(serviceProvider));
- if (logger == null) throw new ArgumentNullException(nameof(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);
- _httpContextKey = GetType().FullName;
- }
-
- ServiceProvider = serviceProvider;
- Logger = logger;
- LifetimeScope = scope;
-
- _instanceTypes = new List();
-
- if (scope == ObjectLifetimeScope.Application)
- InitializeAppInstances();
- }
-
- ///
- /// Initializes a new instance of the class with an empty list of objects,
- /// with creation of objects based on an HttpRequest lifetime scope.
- ///
- ///
- ///
- /// The HttpContextBase corresponding to the HttpRequest.
- /// is null.
- protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext)
- {
- if (serviceProvider == null) throw new ArgumentNullException(nameof(serviceProvider));
- if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
- CanResolveBeforeFrozen = false;
- Logger = logger;
- LifetimeScope = ObjectLifetimeScope.HttpRequest;
- _httpContextKey = GetType().FullName;
- ServiceProvider = serviceProvider;
- CurrentHttpContext = httpContext;
- _instanceTypes = new List();
- }
-
- ///
- /// Initializes a new instance of the class with an initial list of object types,
- /// and an optional lifetime scope.
- ///
- ///
- ///
- /// The list of object types.
- /// The lifetime scope of instantiated objects, default is per Application.
- /// If is per HttpRequest then there must be a current HttpContext.
- /// is per HttpRequest but the current HttpContext is null.
- protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
- : this(serviceProvider, logger, scope)
- {
- _instanceTypes = value.ToList();
- }
-
- #endregion
-
- private void InitializeAppInstances()
- {
- _applicationInstances = new Lazy>(() => CreateInstances().ToArray());
- }
-
- ///
- /// Gets or sets a value indicating whether the resolver can resolve objects before resolution is frozen.
- ///
- /// This is false by default and is used for some special internal resolvers.
- internal bool CanResolveBeforeFrozen { get; set; }
-
- ///
- /// Gets the list of types to create instances from.
- ///
- protected virtual IEnumerable InstanceTypes => _instanceTypes;
-
- ///
- /// Gets or sets the used to initialize this object, if any.
- ///
- /// If not null, then LifetimeScope will be ObjectLifetimeScope.HttpRequest.
- protected HttpContextBase CurrentHttpContext { get; }
-
- ///
- /// Returns the service provider used to instantiate objects
- ///
- public IServiceProvider ServiceProvider { get; }
-
- public ILogger Logger { get; }
-
- ///
- /// Gets or sets the lifetime scope of resolved objects.
- ///
- protected ObjectLifetimeScope LifetimeScope { get; }
-
- ///
- /// Gets the resolved object instances, sorted by weight.
- ///
- /// The sorted resolved object instances.
- ///
- /// The order is based upon the WeightedPluginAttribute and DefaultPluginWeight.
- /// Weights are sorted ascendingly (lowest weights come first).
- ///
- protected IEnumerable GetSortedValues()
- {
- if (_sortedValues != null) return _sortedValues;
-
- var values = Values.ToList();
- values.Sort((f1, f2) => GetObjectWeight(f1).CompareTo(GetObjectWeight(f2)));
- _sortedValues = values;
- return _sortedValues;
- }
-
- ///
- /// Gets or sets the default type weight.
- ///
- /// Determines the weight of types that do not have a WeightedPluginAttribute set on
- /// them, when calling GetSortedValues.
- protected virtual int DefaultPluginWeight { get; set; } = 10;
-
- ///
- /// Returns the weight of an object for user with GetSortedValues
- ///
- ///
- ///
- protected virtual int GetObjectWeight(object o)
- {
- var type = o.GetType();
- var attr = type.GetCustomAttribute(true);
- return attr?.Weight ?? DefaultPluginWeight;
- }
-
- ///
- /// Gets the resolved object instances.
- ///
- /// CanResolveBeforeFrozen is false, and resolution is not frozen.
- protected IEnumerable Values => CreateValues(LifetimeScope);
-
- ///
- /// Creates the values collection based on the scope
- ///
- ///
- ///
- protected virtual IEnumerable CreateValues(ObjectLifetimeScope scope)
- {
- using (Resolution.Reader(CanResolveBeforeFrozen))
- {
- // 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
- // instances have actually been instanciated when we return.
-
- switch (LifetimeScope)
- {
- case ObjectLifetimeScope.HttpRequest:
-
- // create new instances per HttpContext
- if (CurrentHttpContext.Items[_httpContextKey] == null)
- {
- var instances = CreateInstances().ToArray();
- var disposableInstances = instances.OfType();
- //Ensure anything resolved that is IDisposable is disposed when the request termintates
- foreach (var disposable in disposableInstances)
- {
- CurrentHttpContext.DisposeOnPipelineCompleted(disposable);
- }
- CurrentHttpContext.Items[_httpContextKey] = instances;
- }
- return (TResolved[])CurrentHttpContext.Items[_httpContextKey];
-
- case ObjectLifetimeScope.Application:
-
- return _applicationInstances.Value;
-
- case ObjectLifetimeScope.Transient:
- default:
- // create new instances each time
- return CreateInstances().ToArray();
- }
- }
- }
-
- ///
- /// Instantiates the object instances for the types contained in the types collection.
- ///
- /// A list of objects of type .
- protected virtual IEnumerable CreateInstances()
- {
- return ServiceProvider.CreateInstances(InstanceTypes, Logger);
- }
-
- #region Types collection manipulation
-
- ///
- /// Removes a type.
- ///
- /// The type to remove.
- /// the resolver does not support removing types, or
- /// the type is not a valid type for the resolver.
- public virtual void RemoveType(Type value)
- {
- EnsureSupportsRemove();
-
- using (Resolution.Configuration)
- using (var l = new UpgradeableReadLock(_lock))
- {
- EnsureCorrectType(value);
-
- l.UpgradeToWriteLock();
- _instanceTypes.Remove(value);
- }
- }
-
- ///
- /// Removes a type.
- ///
- /// The type to remove.
- /// the resolver does not support removing types, or
- /// the type is not a valid type for the resolver.
- public void RemoveType()
- where T : TResolved
- {
- RemoveType(typeof(T));
- }
-
- ///
- /// Adds types.
- ///
- /// The types to add.
- /// The types are appended at the end of the list.
- /// the resolver does not support adding types, or
- /// a type is not a valid type for the resolver, or a type is already in the collection of types.
- protected void AddTypes(IEnumerable types)
- {
- EnsureSupportsAdd();
-
- using (Resolution.Configuration)
- using (new WriteLock(_lock))
- {
- foreach (var t in types)
- {
- EnsureCorrectType(t);
- if (_instanceTypes.Contains(t))
- {
- throw new InvalidOperationException(string.Format(
- "Type {0} is already in the collection of types.", t.FullName));
- }
- _instanceTypes.Add(t);
- }
- }
- }
-
- ///
- /// Adds a type.
- ///
- /// The type to add.
- /// The type is appended at the end of the list.
- /// the resolver does not support adding types, or
- /// the type is not a valid type for the resolver, or the type is already in the collection of types.
- public virtual void AddType(Type value)
- {
- EnsureSupportsAdd();
-
- using (Resolution.Configuration)
- using (var l = new UpgradeableReadLock(_lock))
- {
- EnsureCorrectType(value);
- if (_instanceTypes.Contains(value))
- {
- throw new InvalidOperationException(string.Format(
- "Type {0} is already in the collection of types.", value.FullName));
- }
-
- l.UpgradeToWriteLock();
- _instanceTypes.Add(value);
- }
- }
-
- ///
- /// Adds a type.
- ///
- /// The type to add.
- /// The type is appended at the end of the list.
- /// the resolver does not support adding types, or
- /// the type is not a valid type for the resolver, or the type is already in the collection of types.
- public void AddType()
- where T : TResolved
- {
- AddType(typeof(T));
- }
-
- ///
- /// Clears the list of types
- ///
- /// the resolver does not support clearing types.
- public virtual void Clear()
- {
- EnsureSupportsClear();
-
- using (Resolution.Configuration)
- using (new WriteLock(_lock))
- {
- _instanceTypes.Clear();
- }
- }
-
- ///
- /// WARNING! Do not use this unless you know what you are doing, clear all types registered and instances
- /// created. Typically only used if a resolver is no longer used in an application and memory is to be GC'd
- ///
- internal void ResetCollections()
- {
- using (new WriteLock(_lock))
- {
- _instanceTypes.Clear();
- _sortedValues = null;
- _applicationInstances = null;
- }
- }
-
- ///
- /// Inserts a type at the specified index.
- ///
- /// The zero-based index at which the type should be inserted.
- /// The type to insert.
- /// the resolver does not support inserting types, or
- /// the type is not a valid type for the resolver, or the type is already in the collection of types.
- /// is out of range.
- public virtual void InsertType(int index, Type value)
- {
- EnsureSupportsInsert();
-
- using (Resolution.Configuration)
- using (var l = new UpgradeableReadLock(_lock))
- {
- EnsureCorrectType(value);
- if (_instanceTypes.Contains(value))
- {
- throw new InvalidOperationException(string.Format(
- "Type {0} is already in the collection of types.", value.FullName));
- }
-
- l.UpgradeToWriteLock();
- _instanceTypes.Insert(index, value);
- }
- }
-
- ///
- /// Inserts a type at the beginning of the list.
- ///
- /// The type to insert.
- /// the resolver does not support inserting types, or
- /// the type is not a valid type for the resolver, or the type is already in the collection of types.
- public virtual void InsertType(Type value)
- {
- InsertType(0, value);
- }
-
- ///
- /// Inserts a type at the specified index.
- ///
- /// The type to insert.
- /// The zero-based index at which the type should be inserted.
- /// is out of range.
- public void InsertType(int index)
- where T : TResolved
- {
- InsertType(index, typeof(T));
- }
-
- ///
- /// Inserts a type at the beginning of the list.
- ///
- /// The type to insert.
- public void InsertType()
- where T : TResolved
- {
- InsertType(0, typeof(T));
- }
-
- ///
- /// Inserts a type before a specified, already existing type.
- ///
- /// The existing type before which to insert.
- /// The type to insert.
- /// the resolver does not support inserting types, or
- /// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
- /// or the new type is already in the collection of types.
- public virtual void InsertTypeBefore(Type existingType, Type value)
- {
- EnsureSupportsInsert();
-
- using (Resolution.Configuration)
- using (var l = new UpgradeableReadLock(_lock))
- {
- EnsureCorrectType(existingType);
- EnsureCorrectType(value);
- if (_instanceTypes.Contains(existingType) == false)
- {
- throw new InvalidOperationException(string.Format(
- "Type {0} is not in the collection of types.", existingType.FullName));
- }
- if (_instanceTypes.Contains(value))
- {
- throw new InvalidOperationException(string.Format(
- "Type {0} is already in the collection of types.", value.FullName));
- }
- int index = _instanceTypes.IndexOf(existingType);
-
- l.UpgradeToWriteLock();
- _instanceTypes.Insert(index, value);
- }
- }
-
- ///
- /// Inserts a type before a specified, already existing type.
- ///
- /// The existing type before which to insert.
- /// The type to insert.
- /// the resolver does not support inserting types, or
- /// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
- /// or the new type is already in the collection of types.
- public void InsertTypeBefore()
- where TExisting : TResolved
- where T : TResolved
- {
- InsertTypeBefore(typeof(TExisting), typeof(T));
- }
-
- ///
- /// Returns a value indicating whether the specified type is already in the collection of types.
- ///
- /// The type to look for.
- /// A value indicating whether the type is already in the collection of types.
- public virtual bool ContainsType(Type value)
- {
- using (new ReadLock(_lock))
- {
- return _instanceTypes.Contains(value);
- }
- }
-
- ///
- /// Gets the types in the collection of types.
- ///
- /// The types in the collection of types.
- /// Returns an enumeration, the list cannot be modified.
- public virtual IEnumerable GetTypes()
- {
- Type[] types;
- using (new ReadLock(_lock))
- {
- types = _instanceTypes.ToArray();
- }
- return types;
- }
-
- ///
- /// Returns a value indicating whether the specified type is already in the collection of types.
- ///
- /// The type to look for.
- /// A value indicating whether the type is already in the collection of types.
- public bool ContainsType()
- where T : TResolved
- {
- return ContainsType(typeof(T));
- }
-
- #endregion
-
- ///
- /// Returns a WriteLock to use when modifying collections
- ///
- ///
- protected WriteLock GetWriteLock()
- {
- return new WriteLock(_lock);
- }
-
- #region Type utilities
-
- ///
- /// Ensures that a type is a valid type for the resolver.
- ///
- /// The type to test.
- /// the type is not a valid type for the resolver.
- protected virtual void EnsureCorrectType(Type value)
- {
- if (TypeHelper.IsTypeAssignableFrom(value) == false)
- throw new InvalidOperationException(string.Format(
- "Type {0} is not an acceptable type for resolver {1}.", value.FullName, GetType().FullName));
- }
-
- #endregion
-
- #region Types collection manipulation support
-
- ///
- /// Ensures that the resolver supports removing types.
- ///
- /// The resolver does not support removing types.
- protected void EnsureSupportsRemove()
- {
- if (SupportsRemove == false)
- throw new InvalidOperationException("This resolver does not support removing types");
- }
-
- ///
- /// Ensures that the resolver supports clearing types.
- ///
- /// The resolver does not support clearing types.
- protected void EnsureSupportsClear()
- {
- if (SupportsClear == false)
- throw new InvalidOperationException("This resolver does not support clearing types");
- }
-
- ///
- /// Ensures that the resolver supports adding types.
- ///
- /// The resolver does not support adding types.
- protected void EnsureSupportsAdd()
- {
- if (SupportsAdd == false)
- throw new InvalidOperationException("This resolver does not support adding new types");
- }
-
- ///
- /// Ensures that the resolver supports inserting types.
- ///
- /// The resolver does not support inserting types.
- protected void EnsureSupportsInsert()
- {
- if (SupportsInsert == false)
- throw new InvalidOperationException("This resolver does not support inserting new types");
- }
-
- ///
- /// Gets a value indicating whether the resolver supports adding types.
- ///
- protected virtual bool SupportsAdd
- {
- get { return true; }
- }
-
- ///
- /// Gets a value indicating whether the resolver supports inserting types.
- ///
- protected virtual bool SupportsInsert
- {
- get { return true; }
- }
-
- ///
- /// Gets a value indicating whether the resolver supports clearing types.
- ///
- protected virtual bool SupportsClear
- {
- get { return true; }
- }
-
- ///
- /// Gets a value indicating whether the resolver supports removing types.
- ///
- protected virtual bool SupportsRemove
- {
- get { return true; }
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Core/ObjectResolution/WeightedPluginAttribute.cs b/src/Umbraco.Core/ObjectResolution/WeightedPluginAttribute.cs
deleted file mode 100644
index 323142bd4c..0000000000
--- a/src/Umbraco.Core/ObjectResolution/WeightedPluginAttribute.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-
-namespace Umbraco.Core.ObjectResolution
-{
- ///
- /// Indicates the relative weight of a resolved object type.
- ///
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
- internal class WeightedPluginAttribute : Attribute
- {
- ///
- /// Initializes a new instance of the class with a weight.
- ///
- /// The object type weight.
- public WeightedPluginAttribute(int weight)
- {
- Weight = weight;
- }
-
- ///
- /// Gets or sets the weight of the object type.
- ///
- public int Weight { get; private set; }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 8ceb9d7bbf..8c32f10f94 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -306,7 +306,6 @@
-
@@ -1119,7 +1118,6 @@
-
@@ -1141,7 +1139,6 @@
-
diff --git a/src/Umbraco.Tests/Resolvers/CollectionBuildersTests.cs b/src/Umbraco.Tests/Resolvers/CollectionBuildersTests.cs
new file mode 100644
index 0000000000..4fbf66aa96
--- /dev/null
+++ b/src/Umbraco.Tests/Resolvers/CollectionBuildersTests.cs
@@ -0,0 +1,475 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using LightInject;
+using NUnit.Framework;
+using Umbraco.Core.DependencyInjection;
+
+namespace Umbraco.Tests.Resolvers
+{
+ [TestFixture]
+ public class CollectionBuildersTests
+ {
+ private ServiceContainer _container;
+
+ [SetUp]
+ public void Setup()
+ {
+ Current.Reset();
+
+ _container = new ServiceContainer();
+ _container.ConfigureUmbracoCore();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Current.Reset();
+
+ _container.Dispose();
+ _container = null;
+ }
+
+ #region Test objects
+
+ public abstract class Resolved
+ { }
+
+ public class Resolved1 : Resolved
+ { }
+
+ [Weight(5)] // default is 10
+ public class Resolved2 : Resolved
+ { }
+
+ public class Resolved3 : Resolved
+ { }
+
+ public class Resolved4 // not! : Resolved
+ { }
+
+ private class TestCollectionBuilder : OrderedCollectionBuilderBase
+ {
+ public TestCollectionBuilder(IServiceContainer container)
+ : base(container)
+ { }
+
+ protected override TestCollectionBuilder This => this;
+ }
+
+ private class TestCollectionBuilderTransient : OrderedCollectionBuilderBase
+ {
+ public TestCollectionBuilderTransient(IServiceContainer container)
+ : base(container)
+ { }
+
+ protected override TestCollectionBuilderTransient This => this;
+
+ protected override ILifetime CollectionLifetime => null; // transient
+ }
+
+ private class TestCollectionBuilderScope : OrderedCollectionBuilderBase
+ {
+ public TestCollectionBuilderScope(IServiceContainer container)
+ : base(container)
+ { }
+
+ protected override TestCollectionBuilderScope This => this;
+
+ protected override ILifetime CollectionLifetime => new PerScopeLifetime();
+ }
+
+ private class TestCollectionBuilderWeighted : WeightedCollectionBuilderBase
+ {
+ public TestCollectionBuilderWeighted(IServiceContainer container)
+ : base(container)
+ { }
+
+ protected override TestCollectionBuilderWeighted This => this;
+ }
+
+ private class TestCollection : BuilderCollectionBase
+ {
+ public TestCollection(IEnumerable items)
+ : base(items)
+ { }
+ }
+
+ #endregion
+
+ [Test]
+ public void ContainsTypes()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ Assert.IsTrue(builder.Has());
+ Assert.IsTrue(builder.Has());
+ Assert.IsFalse(builder.Has());
+ //Assert.IsFalse(col.ContainsType()); // does not compile
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved1), typeof(Resolved2));
+ }
+
+ [Test]
+ public void Clear()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ builder.Clear();
+ Assert.IsFalse(builder.Has());
+ Assert.IsFalse(builder.Has());
+
+ var col = builder.CreateCollection();
+ AssertCollection(col);
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void ClearOnceResolved()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ var col = builder.CreateCollection();
+ builder.Clear();
+ }
+
+ [Test]
+ public void Append()
+ {
+ var builder = TestCollectionBuilder.Register(_container);
+ builder.Append();
+ builder.Append();
+
+ Assert.IsTrue(builder.Has());
+ Assert.IsTrue(builder.Has());
+ Assert.IsFalse(builder.Has());
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved1), typeof(Resolved2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void AppendOnceResolved()
+ {
+ var builder = TestCollectionBuilder.Register(_container);
+
+ var col = builder.CreateCollection();
+ builder.Append();
+ }
+
+ [Test]
+ public void AppendDuplicate()
+ {
+ var builder = TestCollectionBuilder.Register(_container);
+ builder.Append();
+ builder.Append();
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved1));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void AppendInvalid()
+ {
+ var builder = TestCollectionBuilder.Register(_container);
+ //builder.Append(); // does not compile
+ builder.Append(new[] { typeof(Resolved4) }); // throws
+ }
+
+ [Test]
+ public void Remove()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append()
+ .Remove();
+
+ Assert.IsTrue(builder.Has());
+ Assert.IsFalse(builder.Has());
+ Assert.IsFalse(builder.Has());
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved1));
+ }
+
+ [Test]
+ public void RemoveAbsent()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append()
+ .Remove();
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved1), typeof(Resolved2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void RemoveOnceResolved()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ var col = builder.CreateCollection();
+ builder.Remove(); // throws
+ }
+
+ [Test]
+ public void Insert()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append()
+ .Insert();
+
+ Assert.IsTrue(builder.Has());
+ Assert.IsTrue(builder.Has());
+ Assert.IsTrue(builder.Has());
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved3), typeof(Resolved1), typeof(Resolved2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void InsertOnceResolved()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ var col = builder.CreateCollection();
+ builder.Insert(); // throws
+ }
+
+ [Test]
+ public void CanInsertDuplicate()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append()
+ .Insert();
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved2), typeof(Resolved1));
+ }
+
+ [Test]
+ public void InsertInEmpty()
+ {
+ var builder = TestCollectionBuilder.Register(_container);
+ builder.Insert();
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]
+ public void InsertAtWrongIndex1()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ builder.Insert(99); // throws
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]
+ public void InsertAtWrongIndex2()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ builder.Insert(-1); // throws
+ }
+
+ [Test]
+ public void InsertBefore()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append()
+ .InsertBefore();
+
+ Assert.IsTrue(builder.Has());
+ Assert.IsTrue(builder.Has());
+ Assert.IsTrue(builder.Has());
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved1), typeof(Resolved3), typeof(Resolved2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void InsertBeforeOnceResolved()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ var col = builder.CreateCollection();
+ builder.InsertBefore();
+ }
+
+ [Test]
+ public void InsertBeforeDuplicate()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append()
+ .InsertBefore();
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved2), typeof(Resolved1));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void InsertBeforeAbsent()
+ {
+ var builder = TestCollectionBuilder.Register(_container)
+ .Append()
+ .InsertBefore();
+ }
+
+ [Test]
+ public void ScopeIsApplication()
+ {
+ TestCollectionBuilder.Register(_container)
+ .Append()
+ .Append();
+
+ // CreateCollection creates a new collection each time
+ // but the container manages the scope, so to test the scope
+ // the collection must come from the container
+
+ var col1 = _container.GetInstance();
+ AssertCollection(col1, typeof(Resolved1), typeof(Resolved2));
+
+ var col2 = _container.GetInstance();
+ AssertCollection(col2, typeof(Resolved1), typeof(Resolved2));
+
+ AssertSameCollection(col1, col2);
+ }
+
+ [Test]
+ public void ScopeIsTransient()
+ {
+ TestCollectionBuilderTransient.Register(_container)
+ .Append()
+ .Append();
+
+ // CreateCollection creates a new collection each time
+ // but the container manages the scope, so to test the scope
+ // the collection must come from the container
+
+ var col1 = _container.GetInstance();
+ AssertCollection(col1, typeof(Resolved1), typeof(Resolved2));
+
+ var col2 = _container.GetInstance();
+ AssertCollection(col1, typeof(Resolved1), typeof(Resolved2));
+
+ AssertNotSameCollection(col1, col2);
+ }
+
+ [Test]
+ public void OrderOfTypes()
+ {
+ var builder = TestCollectionBuilderTransient.Register(_container)
+ .Append()
+ .Insert()
+ .InsertBefore();
+
+ var col1 = builder.CreateCollection();
+ AssertCollection(col1, typeof(Resolved1), typeof(Resolved2), typeof(Resolved3));
+ }
+
+ [Test]
+ public void ScopeIsScope()
+ {
+ TestCollectionBuilderScope.Register(_container)
+ .Append()
+ .Append();
+
+ // CreateCollection creates a new collection each time
+ // but the container manages the scope, so to test the scope
+ // the collection must come from the container
+
+ var scope1 = _container.BeginScope();
+
+ var col1A = _container.GetInstance();
+ AssertCollection(col1A, typeof(Resolved1), typeof(Resolved2));
+ var col1B = _container.GetInstance();
+ AssertCollection(col1B, typeof(Resolved1), typeof(Resolved2));
+
+ AssertSameCollection(col1A, col1B);
+
+ _container.EndCurrentScope();
+ var scope2 = _container.BeginScope();
+
+ var col2 = _container.GetInstance();
+ AssertCollection(col2, typeof(Resolved1), typeof(Resolved2));
+
+ AssertNotSameCollection(col1A, col2);
+
+ _container.EndCurrentScope();
+ }
+
+ [Test]
+ public void Weights()
+ {
+ var builder = TestCollectionBuilderWeighted.Register(_container)
+ .Add()
+ .Add();
+
+ var col = builder.CreateCollection();
+ AssertCollection(col, typeof(Resolved2), typeof(Resolved1));
+ }
+
+ private static void AssertCollection(IEnumerable col, params Type[] expected)
+ {
+ var colA = col.ToArray();
+ Assert.AreEqual(expected.Length, colA.Length);
+ for (var i = 0; i < expected.Length; i++)
+ Assert.IsInstanceOf(expected[i], colA[i]);
+ }
+
+ private static void AssertSameCollection(IEnumerable col1, IEnumerable col2)
+ {
+ Assert.AreSame(col1, col2);
+
+ var col1A = col1.ToArray();
+ var col2A = col2.ToArray();
+
+ Assert.AreEqual(col1A.Length, col2A.Length);
+ for (var i = 0; i < col1A.Length; i++)
+ Assert.AreSame(col1A[i], col2A[i]);
+ }
+
+ private static void AssertNotSameCollection(IEnumerable col1, IEnumerable col2)
+ {
+ Assert.AreNotSame(col1, col2);
+
+ var col1A = col1.ToArray();
+ var col2A = col2.ToArray();
+
+ Assert.AreEqual(col1A.Length, col2A.Length);
+ for (var i = 0; i < col1A.Length; i++)
+ Assert.AreNotSame(col1A[i], col2A[i]);
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/Resolvers/ManyResolverTests.cs b/src/Umbraco.Tests/Resolvers/ManyResolverTests.cs
deleted file mode 100644
index 4cf1c3b56f..0000000000
--- a/src/Umbraco.Tests/Resolvers/ManyResolverTests.cs
+++ /dev/null
@@ -1,409 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Web;
-using Moq;
-using Umbraco.Core;
-using Umbraco.Core.Logging;
-using Umbraco.Core.ObjectResolution;
-using Umbraco.Tests.TestHelpers;
-
-using NUnit.Framework;
-
-namespace Umbraco.Tests.Resolvers
-{
- [TestFixture]
- public class ManyResolverTests
- {
- [SetUp]
- public void Setup()
- {
- ManyResolver.Reset();
- }
-
- [TearDown]
- public void TearDown()
- {
- ManyResolver.Reset();
- }
-
- #region Resolvers and Resolved
-
- public abstract class Resolved
- { }
-
- public class Resolved1 : Resolved
- { }
-
- [WeightedPlugin(5)] // default is 10
- public class Resolved2 : Resolved
- { }
-
- public class Resolved3 : Resolved
- { }
-
- public class Resolved4 // not! : Resolved
- { }
-
- public sealed class ManyResolver : ManyObjectsResolverBase
- {
- public ManyResolver(IServiceProvider serviceProvider, ILogger logger)
- : base(serviceProvider, logger)
- { }
-
- public ManyResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable value)
- : base(serviceProvider, logger, value)
- { }
-
- public ManyResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable value, ObjectLifetimeScope scope)
- : base(serviceProvider, logger, value, scope)
- { }
-
- public ManyResolver(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext)
- : base(serviceProvider, logger, httpContext)
- { }
-
- public IEnumerable SortedResolvedObjects { get { return GetSortedValues(); } }
- public IEnumerable ResolvedObjects { get { return Values; } }
- }
-
- #endregion
-
- #region Test ManyResolver types collection manipulation
-
- [Test]
- public void ManyResolverContainsTypes()
- {
- var resolver = new ManyResolver(
- new ActivatorServiceProvider(), Mock.Of(),
- new Type[] { typeof(Resolved1), typeof(Resolved2) });
-
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsFalse(resolver.ContainsType());
- //Assert.IsFalse(resolver.ContainsType()); // does not compile
- }
-
- [Test]
- public void ManyResolverCanClearBeforeFreeze()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- resolver.AddType();
- resolver.AddType();
- resolver.Clear();
- Assert.IsFalse(resolver.ContainsType());
- Assert.IsFalse(resolver.ContainsType());
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotClearOnceFrozen()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- resolver.AddType();
- resolver.AddType();
- Resolution.Freeze();
- resolver.Clear();
- }
-
- [Test]
- public void ManyResolverCanAddTypeBeforeFreeze()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- resolver.AddType();
- resolver.AddType();
-
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsFalse(resolver.ContainsType());
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotAddTypeOnceFrozen()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- Resolution.Freeze();
- resolver.AddType();
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotAddTypeAgain()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- resolver.AddType();
- resolver.AddType();
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotAddInvalidType()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- //resolver.AddType(); // does not compile
- resolver.AddType(typeof(Resolved4)); // throws
- }
-
- [Test]
- public void ManyResolverCanRemoveTypeBeforeFreeze()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.RemoveType();
-
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsFalse(resolver.ContainsType());
- Assert.IsFalse(resolver.ContainsType());
- }
-
- [Test]
- public void ManyResolverCanRemoveAbsentType()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.RemoveType();
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotRemoveInvalidType()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- //resolver.RemoveType(); // does not compile
- resolver.RemoveType(typeof(Resolved4)); // throws
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotRemoveTypeOnceFrozen()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- Resolution.Freeze();
- resolver.RemoveType(); // throws
- }
-
- [Test]
- public void ManyResolverCanInsertTypeBeforeFreeze()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.InsertType(0);
-
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsTrue(resolver.ContainsType());
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotInsertTypeOnceFrozen()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- Resolution.Freeze();
- resolver.InsertType(0);
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotInsertTypeAgain()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.InsertType(0);
- }
-
- [Test]
- public void ManyResolverCanInsertInEmptyList()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- resolver.InsertType();
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotInsertInvalidType()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- //resolver.InsertType(0); // does not compile
- resolver.InsertType(0, typeof(Resolved4)); // throws
- }
-
- [Test]
- [ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void ManyResolverCannotInsertTypeAtWrongIndex()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.InsertType(99, typeof(Resolved3)); // throws
- }
-
- //
-
- [Test]
- public void ManyResolverCanInsertBeforeTypeBeforeFreeze()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.InsertTypeBefore();
-
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsTrue(resolver.ContainsType());
- Assert.IsTrue(resolver.ContainsType());
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotInsertBeforeTypeOnceFrozen()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- Resolution.Freeze();
- resolver.InsertTypeBefore();
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotInsertBeforeTypeAgain()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.InsertTypeBefore();
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotInsertBeforeAbsentType()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1) });
- resolver.InsertTypeBefore();
- }
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotInsertBeforeInvalidType()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- //resolver.InsertTypeBefore(); // does not compile
- resolver.InsertTypeBefore(typeof(Resolved2), typeof(Resolved4)); // throws
- }
-
- #endregion
-
- #region Test ManyResolver resolution
-
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ManyResolverCannotGetValuesBeforeFreeze()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- var values = resolver.ResolvedObjects;
- }
-
- [Test]
- public void ManyResolverCannotGetValuesBeforeFreezeUnless()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- resolver.CanResolveBeforeFrozen = true;
- var values = resolver.ResolvedObjects;
- }
-
- [Test]
- public void ManyResolverCanGetValuesOnceFrozen()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- Resolution.Freeze();
- var values = resolver.ResolvedObjects;
-
- Assert.AreEqual(2, values.Count());
- Assert.IsInstanceOf(values.ElementAt(0));
- Assert.IsInstanceOf(values.ElementAt(1));
- }
-
- [Test]
- public void ManyResolverDefaultLifetimeScopeIsApplication()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- Resolution.Freeze();
- var values = resolver.ResolvedObjects;
-
- Assert.AreEqual(2, values.Count());
- Assert.IsInstanceOf(values.ElementAt(0));
- Assert.IsInstanceOf(values.ElementAt(1));
-
- var values2 = resolver.ResolvedObjects;
- Assert.AreEqual(2, values2.Count());
- Assert.AreSame(values.ElementAt(0), values2.ElementAt(0));
- Assert.AreSame(values.ElementAt(1), values2.ElementAt(1));
- }
-
- [Test]
- public void ManyResolverTransientLifetimeScope()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) }, ObjectLifetimeScope.Transient);
- Resolution.Freeze();
- var values = resolver.ResolvedObjects;
-
- Assert.AreEqual(2, values.Count());
- Assert.IsInstanceOf(values.ElementAt(0));
- Assert.IsInstanceOf(values.ElementAt(1));
-
- var values2 = resolver.ResolvedObjects;
- Assert.AreEqual(2, values2.Count());
- Assert.AreNotSame(values.ElementAt(0), values2.ElementAt(0));
- Assert.AreNotSame(values.ElementAt(1), values2.ElementAt(1));
- }
-
- [Test]
- public void ManyResolverDefaultOrderOfTypes()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of());
- resolver.AddType();
- resolver.InsertType(0);
- resolver.InsertTypeBefore();
- Resolution.Freeze();
- var values = resolver.ResolvedObjects;
-
- Assert.AreEqual(3, values.Count());
- Assert.IsInstanceOf(values.ElementAt(0));
- Assert.IsInstanceOf(values.ElementAt(1));
- Assert.IsInstanceOf(values.ElementAt(2));
- }
-
- [Test]
- public void ManyResolverHttpRequestLifetimeScope()
- {
- var httpContextFactory = new FakeHttpContextFactory("~/Home");
- var httpContext = httpContextFactory.HttpContext;
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), httpContext);
-
- resolver.AddType();
- resolver.AddType();
- Resolution.Freeze();
-
- var values = resolver.ResolvedObjects;
- Assert.AreEqual(2, values.Count());
- Assert.IsInstanceOf(values.ElementAt(0));
- Assert.IsInstanceOf(values.ElementAt(1));
-
- var values2 = resolver.ResolvedObjects;
- Assert.AreEqual(2, values2.Count());
- Assert.AreSame(values.ElementAt(0), values2.ElementAt(0));
- Assert.AreSame(values.ElementAt(1), values2.ElementAt(1));
-
- httpContextFactory.HttpContext.Items.Clear(); // new context
-
- var values3 = resolver.ResolvedObjects;
- Assert.AreEqual(2, values3.Count());
- Assert.AreNotSame(values.ElementAt(0), values3.ElementAt(0));
- Assert.AreNotSame(values.ElementAt(1), values3.ElementAt(1));
- }
-
- [Test]
- public void ManyResolverWeightedResolution()
- {
- var resolver = new ManyResolver(new ActivatorServiceProvider(), Mock.Of(), new Type[] { typeof(Resolved1), typeof(Resolved2) });
- Resolution.Freeze();
-
- var values = resolver.SortedResolvedObjects;
- Assert.AreEqual(2, values.Count());
- Assert.IsInstanceOf(values.ElementAt(0));
- Assert.IsInstanceOf(values.ElementAt(1));
- }
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index d3915c1403..6bd785cca8 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -498,7 +498,7 @@
-
+