Recently we have updated to the version 3.1.4.143 and I have encountered an issue which I am not sure if it’s a bug or a misunderstanding of how it works.
We have a wrapper around structuremap containers called ServiceLocator.Current
The following scenario passes when I am using all transient lifecycles for configuration, but as soon as I use another life cycle (hybrid in this case), the test won’t pass.
Here is the test scenario:
By using the simple structure:
internal class DummyDependencyA : IDummyDependency
{
}
internal class DummyDependencyB : IDummyDependency
{
}
internal interface IDummyDependency
{
}
internal interface IDummyInterface
{
IDummyDependency DummyDependency { get; }
}
internal class DummyImplementation : IDummyInterface
{
public IDummyDependency DummyDependency { get; private set; }
public DummyImplementation(IDummyDependency dummyDependency)
{
DummyDependency = dummyDependency;
}
}
[Test]
public void TestStructureMapInstanceEvictedDependency()
{
// Testing with different lifecycle
// Transiant is the only one that is working from what I've tested
var lifecycleEnum = LifecycleEnum.Hybrid;
// Wrapper call for CurrentContainer.Configure(x => x.For(type).LifecycleIs(GetLifecycle(lifecycle)).Use(resultType));
// Lifecycle used here is new HybridLifecycle()
ServiceLocator.Current.Register<IDummyInterface, DummyImplementation>(lifecycleEnum);
ServiceLocator.Current.Register<IDummyDependency, DummyDependencyA>(lifecycleEnum);
// Wrapper call for CurrentContainer.GetInstance<TService>();
var interface1 = ServiceLocator.Current.GetInstance<IDummyInterface>();
// Success
interface1.DummyDependency.GetType().ShouldBeExactlyType<DummyDependencyA>();
/*
public IServiceLocator BeginTransactionWithNewDiContainer()
{
var nestedContainer = CurrentContainer.GetNestedContainer();
// ThreadStatic IContainer stack
ContainerStack.Push(nestedContainer);
return this;
}
public void Dispose()
{
ContainerStack.Pop();
}
*/
using (ServiceLocator.Current.BeginTransactionWithNewDiContainer())
{
var dummyInterface1 = ServiceLocator.Current.GetInstance<IDummyInterface>();
// Success
dummyInterface1.DummyDependency.GetType().ShouldBeExactlyType<DummyDependencyA>();
var instance = new DummyDependencyB();
Console.WriteLine(ServiceLocator.Current.DescribeBuildPlan<IDummyDependency>());
Console.WriteLine(@"BEFORE RE-REGISTER");
Console.WriteLine(ServiceLocator.Current.WhatDoIHave(typeof(IDummyDependency)));
Console.WriteLine(ServiceLocator.Current.WhatDoIHave(typeof(IDummyInterface)));
// Override current registration with singleton instance for this container scope
ServiceLocator.Current.Register<IDummyDependency>(instance, lifecycleEnum);
Console.WriteLine(ServiceLocator.Current.DescribeBuildPlan<IDummyDependency>());
Console.WriteLine(@"AFTER RE-REGISTER");
Console.WriteLine(ServiceLocator.Current.WhatDoIHave(typeof(IDummyDependency)));
Console.WriteLine(ServiceLocator.Current.WhatDoIHave(typeof(IDummyInterface)));
ServiceLocator.Current.EjectAllInstancesOf<IDummyInterface>();
Console.WriteLine(ServiceLocator.Current.DescribeBuildPlan<IDummyDependency>());
Console.WriteLine(@"AFTER EJECT");
Console.WriteLine(ServiceLocator.Current.WhatDoIHave(typeof(IDummyDependency)));
Console.WriteLine(ServiceLocator.Current.WhatDoIHave(typeof(IDummyInterface)));
var dummyInterface = ServiceLocator.Current.GetInstance<IDummyInterface>();
// Success (it's a different instance)
dummyInterface.ShouldNotBe(dummyInterface1);
////////////////////
// FAIL HERE. dummyInterface.DummyDependency is still type of DummyDependencyA, even after the re-register
////////////////////
dummyInterface.DummyDependency.GetType().ShouldBeExactlyType<DummyDependencyB>();
var @interface = ServiceLocator.Current.GetInstance<IDummyInterface>();
@interface.DummyDependency.ShouldBe(instance);
}
ServiceLocator.Current.GetInstance<IDummyInterface>().DummyDependency.GetType().ShouldBeExactlyType<DummyDependencyA>();
}
Here is the output on the console trace for result of my test in hybrid when it fails:
PluginType: BesLogic.Test.Model.IDummyDependency
Lifecycle: Hybrid
new DummyDependencyA()
BEFORE RE-REGISTER
Nested Container: DEFAULT - Nested
=============================================================================================================
PluginType Namespace Lifecycle Description Name
-------------------------------------------------------------------------------------------------------------
IDummyDependency BesLogic.Test.Model Hybrid BesLogic.Test.Model.DummyDependencyA (Default)
=============================================================================================================
Nested Container: DEFAULT - Nested
===============================================================================================================
PluginType Namespace Lifecycle Description Name
---------------------------------------------------------------------------------------------------------------
IDummyInterface BesLogic.Test.Model Hybrid BesLogic.Test.Model.DummyImplementation (Default)
===============================================================================================================
PluginType: BesLogic.Test.Model.IDummyDependency
Lifecycle: Object
Value: BesLogic.Test.Model.DummyDependencyB
AFTER RE-REGISTER
Nested Container: DEFAULT - Nested
======================================================================================================================
PluginType Namespace Lifecycle Description Name
----------------------------------------------------------------------------------------------------------------------
IDummyDependency BesLogic.Test.Model Object Object: BesLogic.Test.Model.DummyDependencyB (Default)
======================================================================================================================
Nested Container: DEFAULT - Nested
===============================================================================================================
PluginType Namespace Lifecycle Description Name
---------------------------------------------------------------------------------------------------------------
IDummyInterface BesLogic.Test.Model Hybrid BesLogic.Test.Model.DummyImplementation (Default)
===============================================================================================================
PluginType: BesLogic.Test.Model.IDummyDependency
Lifecycle: Object
Value: BesLogic.Test.Model.DummyDependencyB
AFTER EJECT
Nested Container: DEFAULT - Nested
======================================================================================================================
PluginType Namespace Lifecycle Description Name
----------------------------------------------------------------------------------------------------------------------
IDummyDependency BesLogic.Test.Model Object Object: BesLogic.Test.Model.DummyDependencyB (Default)
======================================================================================================================
Nested Container: DEFAULT - Nested
===============================================================================================================
PluginType Namespace Lifecycle Description Name
---------------------------------------------------------------------------------------------------------------
IDummyInterface BesLogic.Test.Model Hybrid BesLogic.Test.Model.DummyImplementation (Default)
===============================================================================================================
Expected: <BesLogic.Test.Model.DummyDependencyB>
But was: <BesLogic.Test.Model.DummyDependencyA>
Expected: <BesLogic.Test.Model.DummyDependencyB> But was: <BesLogic.Test.Model.DummyDependencyA>
at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression, String message, Object[] args) at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression) at BesLogic.Test.Utilities.AssertExtensions.ShouldBeExactlyType(Type o) in AssertExtensions.cs: line 66 at BesLogic.Test.Model.ModelTest.TestStructureMapInstanceEvictedDependency() in ModelTest.cs: line 405
When I run the test with lifecycle as Transient, it passes. Here are the console logs:
PluginType: BesLogic.Test.Model.IDummyDependency
Lifecycle: Transient
new DummyDependencyA()
BEFORE RE-REGISTER
Nested Container: DEFAULT - Nested
=============================================================================================================
PluginType Namespace Lifecycle Description Name
-------------------------------------------------------------------------------------------------------------
IDummyDependency BesLogic.Test.Model Transient BesLogic.Test.Model.DummyDependencyA (Default)
=============================================================================================================
Nested Container: DEFAULT - Nested
===============================================================================================================
PluginType Namespace Lifecycle Description Name
---------------------------------------------------------------------------------------------------------------
IDummyInterface BesLogic.Test.Model Transient BesLogic.Test.Model.DummyImplementation (Default)
===============================================================================================================
PluginType: BesLogic.Test.Model.IDummyDependency
Lifecycle: Object
Value: BesLogic.Test.Model.DummyDependencyB
AFTER RE-REGISTER
Nested Container: DEFAULT - Nested
======================================================================================================================
PluginType Namespace Lifecycle Description Name
----------------------------------------------------------------------------------------------------------------------
IDummyDependency BesLogic.Test.Model Object Object: BesLogic.Test.Model.DummyDependencyB (Default)
======================================================================================================================
Nested Container: DEFAULT - Nested
===============================================================================================================
PluginType Namespace Lifecycle Description Name
---------------------------------------------------------------------------------------------------------------
IDummyInterface BesLogic.Test.Model Transient BesLogic.Test.Model.DummyImplementation (Default)
===============================================================================================================
PluginType: BesLogic.Test.Model.IDummyDependency
Lifecycle: Object
Value: BesLogic.Test.Model.DummyDependencyB
AFTER EJECT
Nested Container: DEFAULT - Nested
======================================================================================================================
PluginType Namespace Lifecycle Description Name
----------------------------------------------------------------------------------------------------------------------
IDummyDependency BesLogic.Test.Model Object Object: BesLogic.Test.Model.DummyDependencyB (Default)
======================================================================================================================
Nested Container: DEFAULT - Nested
===============================================================================================================
PluginType Namespace Lifecycle Description Name
---------------------------------------------------------------------------------------------------------------
IDummyInterface BesLogic.Test.Model Transient BesLogic.Test.Model.DummyImplementation (Default)
===============================================================================================================Am I doing anything wrong?
...
--
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-us...@googlegroups.com.
To post to this group, send email to structure...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/structuremap-users/805f4eed-185f-4979-a42c-ea4182e67266%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
[Test]
public void TestStructureMapLifecycles()
{
ILifecycle lifecycle = new TransientLifecycle();
var container = new Container(x =>
{
x.For<IDummyInterface>(lifecycle).Use<DummyImplementation>();
x.For<IDummyDependency>(lifecycle).Use<DummyDependencyA>();
});
IContainer childContainer = container.GetNestedContainer();
// Success!
container.GetInstance<IDummyInterface>().ShouldNotBe(container.GetInstance<IDummyInterface>());
// Success!
childContainer.GetInstance<IDummyInterface>().ShouldBe(childContainer.GetInstance<IDummyInterface>());
}To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsub...@googlegroups.com.