- fix circular dependency check:

- remove successfully resolved objects from the resolve stack
  - add special test case that checks for a situation where this could be wrong
pull/32/head
Simon Gockner 6 years ago
parent c86f604ec3
commit 75f2cc9316
  1. 18
      LightweightIocContainer/IocContainer.cs
  2. 67
      Test.LightweightIocContainer/IocContainerRecursionTest.cs

@ -207,25 +207,31 @@ namespace LightweightIocContainer
else //not the first resolve call in chain but no circular dependencies for now
resolveStack.Add(typeof(T)); //add currently resolving type to the stack
T resolvedInstance;
if (registration is IUnitTestCallbackRegistration<T> unitTestCallbackRegistration)
{
return unitTestCallbackRegistration.UnitTestResolveCallback.Invoke(arguments);
resolvedInstance = unitTestCallbackRegistration.UnitTestResolveCallback.Invoke(arguments);
}
else if (registration is IDefaultRegistration<T> defaultRegistration)
{
if (defaultRegistration.Lifestyle == Lifestyle.Singleton)
return GetOrCreateSingletonInstance(defaultRegistration, arguments, resolveStack);
resolvedInstance = GetOrCreateSingletonInstance(defaultRegistration, arguments, resolveStack);
else if (defaultRegistration is IMultitonRegistration<T> multitonRegistration && defaultRegistration.Lifestyle == Lifestyle.Multiton)
return GetOrCreateMultitonInstance(multitonRegistration, arguments, resolveStack);
return CreateInstance(defaultRegistration, arguments, resolveStack);
resolvedInstance = GetOrCreateMultitonInstance(multitonRegistration, arguments, resolveStack);
else
resolvedInstance = CreateInstance(defaultRegistration, arguments, resolveStack);
}
else if (registration is ITypedFactoryRegistration<T> typedFactoryRegistration)
{
return typedFactoryRegistration.Factory.Factory;
resolvedInstance = typedFactoryRegistration.Factory.Factory;
}
else
throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}.");
resolveStack.Remove(typeof(T)); //T was successfully resolved -> no circular dependency -> remove from resolve stack
return resolvedInstance;
}
/// <summary>

@ -14,7 +14,7 @@ namespace Test.LightweightIocContainer
[TestFixture]
public class IocContainerRecursionTest
{
#region TestClasses
#region TestClassesCircularDependency
[UsedImplicitly]
public interface IFoo
@ -44,7 +44,51 @@ namespace Test.LightweightIocContainer
}
}
#endregion TestClasses
#endregion TestClassesCircularDependency
#region TestClassesNonCircularDependency
[UsedImplicitly]
public interface IA
{
}
[UsedImplicitly]
public interface IB
{
}
[UsedImplicitly]
public interface IC
{
}
[UsedImplicitly]
private class A : IA
{
public A(IB b, IC c)
{
}
}
[UsedImplicitly]
private class B : IB
{
public B(IC c)
{
}
}
[UsedImplicitly]
private class C : IC
{
}
#endregion TestClassesNonCircularDependency
@ -54,9 +98,6 @@ namespace Test.LightweightIocContainer
public void SetUp()
{
_iocContainer = new IocContainer();
_iocContainer.Register<IFoo, Foo>();
_iocContainer.Register<IBar, Bar>();
}
[TearDown]
@ -68,6 +109,9 @@ namespace Test.LightweightIocContainer
[Test]
public void TestCircularDependencies()
{
_iocContainer.Register<IFoo, Foo>();
_iocContainer.Register<IBar, Bar>();
CircularDependencyException exception = Assert.Throws<CircularDependencyException>(() => _iocContainer.Resolve<IFoo>());
Assert.AreEqual(typeof(IFoo), exception.ResolvingType);
Assert.AreEqual(2, exception.ResolveStack.Count);
@ -81,9 +125,22 @@ namespace Test.LightweightIocContainer
Assert.AreEqual(message, exception.Message);
}
[Test]
public void TestNonCircularDependencies()
{
_iocContainer.Register<IA, A>();
_iocContainer.Register<IB, B>();
_iocContainer.Register<IC, C>();
IA a = _iocContainer.Resolve<IA>();
}
[Test]
public void TestRecursionWithParam()
{
_iocContainer.Register<IFoo, Foo>();
_iocContainer.Register<IBar, Bar>();
Assert.DoesNotThrow(() => _iocContainer.Resolve<IFoo>(new Mock<IBar>().Object));
Assert.DoesNotThrow(() => _iocContainer.Resolve<IBar>(new Mock<IFoo>().Object));
}

Loading…
Cancel
Save