This commit is contained in:
Eugene Sadovoi 2019-06-09 21:51:07 -04:00
Родитель 7cd989876b
Коммит 75e3ef8b6d
3 изменённых файлов: 7 добавлений и 331 удалений

Просмотреть файл

@ -16,19 +16,14 @@ namespace Unity
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
var type = key.Type;
var name = key.Name;
var owner = this;
bool adding = true;
int position = 0;
var collisions = 0;
LifetimeManager? manager = null;
ResolveDelegate<BuilderContext>? pipeline = null;
// Add Pipeline to the Registry
lock (_syncRegistry)
{
bool adding = true;
var collisions = 0;
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
@ -71,8 +66,7 @@ namespace Unity
entry.Key = key;
entry.Pipeline = manager.Pipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
_registry.Buckets[targetBucket] = _registry.Count++;
}
if (manager is IDisposable disposable) LifetimeContainer.Add(disposable);

Просмотреть файл

@ -16,15 +16,6 @@ namespace Unity
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
var type = key.Type;
var name = key.Name;
var owner = this;
int position = 0;
var collisions = 0;
bool adding = true;
LifetimeManager? manager = null;
ResolveDelegate<BuilderContext>? pipeline = null;
var typeFactory = (TypeFactoryDelegate)set.Get(typeof(TypeFactoryDelegate));
@ -32,6 +23,8 @@ namespace Unity
// Add Pipeline to the Registry
lock (_syncRegistry)
{
bool adding = true;
var collisions = 0;
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
@ -76,8 +69,7 @@ namespace Unity
entry.Key = key;
entry.Pipeline = manager.Pipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
_registry.Buckets[targetBucket] = _registry.Count++;
}
}
@ -87,7 +79,7 @@ namespace Unity
{
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
{
manager.PipelineDelegate = typeFactory(type, this);
manager.PipelineDelegate = typeFactory(key.Type, this);
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
}
}

Просмотреть файл

@ -1,310 +0,0 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Unity.Tests.v5.Issues
{
[TestClass]
public class GlobalSingletonResolutionFixture
{
[TestMethod]
public void Test_ResolveSignletonInRootContainer_THEN_InstanceIsCreatedInRootContainer()
{
var rootContainer = CreateContainerForTests();
var rootContainerId = rootContainer.GetHashCode();
var childContainer1 = rootContainer.CreateChildContainer();
var childContainer2 = rootContainer.CreateChildContainer();
var reference1 = rootContainer.Resolve<ISingletonService>();
var reference2 = childContainer1.Resolve<ISingletonService>();
var reference3 = childContainer2.Resolve<ISingletonService>();
Assert.AreEqual(reference1, reference2, "reference1 and reference2 must be same");
Assert.AreEqual(reference1, reference3, "reference1 and reference3 must be same");
Assert.AreEqual(rootContainerId, reference1.ContainerId, "Instance by reference1 should be created in root container");
Assert.AreEqual(rootContainerId, reference2.ContainerId, "Instance by reference2 should be created in root container");
Assert.AreEqual(rootContainerId, reference3.ContainerId, "Instance by reference3 should be created in root container");
}
[TestMethod, Ignore("This test will fail until the signleton and all of it dependencies are createde in the root containter")]
public void Test_ResolveSingletonInChildContainer_THEN_InstanceIsCreatedInRootContainer()
{
var rootContainer = CreateContainerForTests();
var rootContainerId = rootContainer.GetHashCode();
var childContainer1 = rootContainer.CreateChildContainer();
var childContainer2 = rootContainer.CreateChildContainer();
var reference1 = childContainer1.Resolve<ISingletonService>();
var reference2 = childContainer2.Resolve<ISingletonService>();
var reference3 = rootContainer.Resolve<ISingletonService>();
Assert.AreEqual(reference1, reference2, "reference1 and reference2 must be same");
Assert.AreEqual(reference1, reference3, "reference1 and reference3 must be same");
Assert.AreEqual(rootContainerId, reference1.ContainerId, "Instance by reference1 should be created in root container");
Assert.AreEqual(rootContainerId, reference2.ContainerId, "Instance by reference2 should be created in root container");
Assert.AreEqual(rootContainerId, reference3.ContainerId, "Instance by reference3 should be created in root container");
}
[TestMethod]
public void Test_UseSignletonInstance_AsFactory_WHEN_ItIsResolvedInRootContainer_THEN_ItCreatesItemsInRootContainer()
{
var rootContainer = CreateContainerForTests();
var rootContainerId = rootContainer.GetHashCode();
var childContainer1 = rootContainer.CreateChildContainer();
var childContainer2 = rootContainer.CreateChildContainer();
var reference1 = rootContainer.Resolve<ISingletonService>();
var reference2 = childContainer1.Resolve<ISingletonService>();
var reference3 = childContainer2.Resolve<ISingletonService>();
var itemsFrom1 = reference1.GetElements();
var itemsFrom2 = reference1.GetElements();
var itemsFrom3 = reference1.GetElements();
Assert.IsTrue(itemsFrom1.All(i => i.ContainerId == rootContainerId), "Not all items from instance by reference1 are created in root container");
Assert.IsTrue(itemsFrom2.All(i => i.ContainerId == rootContainerId), "Not all items from instance by reference2 are created in root container");
Assert.IsTrue(itemsFrom3.All(i => i.ContainerId == rootContainerId), "Not all items from instance by reference3 are created in root container");
}
[TestMethod, Ignore("This test will fail until the signleton and all of it dependencies are createde in the root containter")]
public void Test_UseSignletonInstance_AsFactory_WHEN_ItIsResolvedInChildContainer_THEN_ItCreatesItemsInRootContainer()
{
var rootContainer = CreateContainerForTests();
var rootContainerId = rootContainer.GetHashCode();
var childContainer1 = rootContainer.CreateChildContainer();
var childContainer2 = rootContainer.CreateChildContainer();
var reference1 = childContainer1.Resolve<ISingletonService>();
var reference2 = childContainer2.Resolve<ISingletonService>();
var reference3 = rootContainer.Resolve<ISingletonService>();
var itemsFrom1 = reference1.GetElements();
var itemsFrom2 = reference1.GetElements();
var itemsFrom3 = reference1.GetElements();
Assert.IsTrue(itemsFrom1.All(i => i.ContainerId == rootContainerId), "Not all items from instance by reference1 are created in root container");
Assert.IsTrue(itemsFrom2.All(i => i.ContainerId == rootContainerId), "Not all items from instance by reference2 are created in root container");
Assert.IsTrue(itemsFrom3.All(i => i.ContainerId == rootContainerId), "Not all items from instance by reference3 are created in root container");
}
[TestMethod]
public void Test_UseSignletonInstance_AsFactory_WHEN_ItIsResolvedInRootContainer_AND_ChildContainerIsDisposed_THEN_ItWorksFromRootContainer()
{
var rootContainer = CreateContainerForTests();
rootContainer.Resolve<ISingletonService>();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
childContainer.Dispose();
var items = singleton.GetElements();
Assert.AreEqual(10, items.Count(), "Unexepcted items count");
}
[TestMethod, Ignore("This test will fail until the signleton and all of it dependencies are createde in the root containter")]
public void Test_UseSignletonInstance_AsFactory_WHEN_ItIsResolvedInChildContainer_AND_ChildContainerIsDisposed_THEN_ItWorksFromRootContainer()
{
var rootContainer = CreateContainerForTests();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
childContainer.Dispose();
var items = singleton.GetElements();
Assert.AreEqual(10, items.Count(), "Unexepcted items count");
}
[TestMethod]
public void Test_SingletonDisposing_WHEN_ItIsResolvedInChildContainer_AND_ChildContainerIsDisposed_THEN_ItIs_NotDisposed()
{
var rootContainer = CreateContainerForTests();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
childContainer.Dispose();
Assert.IsFalse(singleton.IsDisposed, "Signleton instance should not be disposed");
}
[TestMethod]
public void Test_SingletonDisposing_WHEN_ItIsResolvedInChildContainer_AND_RootContainerIsDisposed_THEN_ItIs_Disposed()
{
var rootContainer = CreateContainerForTests();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
rootContainer.Dispose();
Assert.IsTrue(singleton.IsDisposed, "Signleton instance should be disposed");
}
[TestMethod]
public void Test_SingletonDisposing_WHEN_ItIsResolvedInRootContainer_AND_ChildContainerIsDisposed_THEN_ItIs_NotDisposed()
{
var rootContainer = CreateContainerForTests();
rootContainer.Resolve<ISingletonService>();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
childContainer.Dispose();
Assert.IsFalse(singleton.IsDisposed, "Signleton instance should not be disposed");
}
[TestMethod]
public void Test_SingletonDisposing_WHEN_ItIsResolvedInRootContainer_AND_RootContainerIsDisposed_THEN_ItIs_Disposed()
{
var rootContainer = CreateContainerForTests();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
rootContainer.Dispose();
Assert.IsTrue(singleton.IsDisposed, "Signleton instance should be disposed");
}
[TestMethod]
public void Test_SingletonCreatedDependenciesDisposing_WHEN_ItIsResolvedInRootContainer_AND_ChildContainerIsDisposed_THEN_ItDependencies_NotDisposed()
{
var rootContainer = CreateContainerForTests();
rootContainer.Resolve<ISingletonService>();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
var items = singleton.GetElements();
childContainer.Dispose();
Assert.IsFalse(items.Any(i => i.IsDisposed), "Items created by signleton should not be disposed");
}
[TestMethod, Ignore("This test will fail until the signleton and all of it dependencies are createde in the root containter")]
public void Test_SingletonCreatedDependenciesDisposing_WHEN_ItIsResolvedInChildContainer_AND_ChildContainerIsDisposed_THEN_ItDependencies_NotDisposed()
{
var rootContainer = CreateContainerForTests();
var childContainer = rootContainer.CreateChildContainer();
var singleton = childContainer.Resolve<ISingletonService>();
var items = singleton.GetElements();
childContainer.Dispose();
Assert.IsFalse(items.Any(i => i.IsDisposed), "Items created by signleton should not be disposed");
}
private IUnityContainer CreateContainerForTests()
{
var target = new UnityContainer();
// transient type registrations, e.g. new instance is created every time
target.RegisterType(typeof(ITestElement), typeof(TestElement));
target.RegisterType(typeof(ITestElementFactory), typeof(TestElementFactory));
// singleton type registration, e.g. same instance every time, from any scope (child or parent containter)
target.RegisterType(typeof(ISingletonService), typeof(SingletonService), TypeLifetime.Singleton);
return target;
}
#region Helper test-types
interface ITestElement : IDisposable
{
bool IsDisposed { get; }
long ContainerId { get; }
}
class TestElement : ITestElement
{
public long ContainerId { get; }
public bool IsDisposed { get; private set; }
public TestElement(IUnityContainer container)
{
ContainerId = container.GetHashCode();
}
public void Dispose()
{
IsDisposed = true;
}
}
interface ITestElementFactory
{
ITestElement CreateElement();
}
interface ISingletonService : IDisposable
{
long ContainerId { get; }
bool IsDisposed { get; }
IEnumerable<ITestElement> GetElements();
}
class TestElementFactory : ITestElementFactory
{
private readonly IUnityContainer _container;
public TestElementFactory(IUnityContainer container)
{
_container = container;
}
public ITestElement CreateElement()
{
return _container.Resolve<ITestElement>();
}
}
class SingletonService : ISingletonService
{
private readonly ITestElementFactory _elementFactory;
public long ContainerId { get; }
public bool IsDisposed { get; private set; }
public SingletonService(IUnityContainer container, ITestElementFactory elementFactory)
{
ContainerId = container.GetHashCode();
_elementFactory = elementFactory;
}
public IEnumerable<ITestElement> GetElements()
{
for (int i = 0; i < 10; i++)
yield return _elementFactory.CreateElement();
}
public void Dispose()
{
IsDisposed = true;
}
}
#endregion
}
}