Structure Map even cooler delayed resolving
Yesterday I wrote a post about nice feature of StructureMap that using no container specific syntax indicate that class dependency should be lazy resolved not construction time resolved. I showed it behaves reasonably when injected type is configured as a singleton.
Today when I was writing some dynamic container reconfiguration changing code (for QA testing purposes) I got concerned. What if such lazy loaded type mapping changes?
The question can be stated as unit test:
[Test]
public void LazyResolveReconfigured()
{
ObjectFactory.Initialize(
container =>
{
container.For<IFoo>().Use<Foo>();
container.For<IBar>().Use<Bar>();
});
var foo = ObjectFactory.GetInstance<IFoo>();
foo.DoSth();
var anotherBar = new AnotherBar();
ObjectFactory.Configure(container => container.For<IBar>().Use(anotherBar));
foo.DoSth();
Assert.IsTrue(anotherBar.DidSth);
}
We resolve IFoo implementation as previously. It depends on IBar, but lazily delivered. We then rewire our container to use AnotherBar for this interface and finally call the IFoo method that depends on the IBar. Would above test pass?
It will! Also if one change the mapping to be singleton like. You must make sure tough that you use Configure to further extend configuration. If you use Initialize then the unit test will fail. Apparently it loses information on the root type and “forgets” to re-wire it.
A quick peek into what exactly is being passed as Func<IBar> brought me to StructureMap.Pipeline.LazyInstance. Yet need to investigate it deeply, but in StructureMap source code I found quite a lot of different Instance implementations – EnumerableInstance in particular. This lead me to the following passing test:
[Test]
public void Enumrable()
{
ObjectFactory.Initialize(
container =>
{
container.For<ISomething>().Use<Something>();
container.For<IBar>().Use<Bar>();
container.For<IBar>().Use<AnotherBar>();
});
var something = ObjectFactory.GetInstance<ISomething>();
Assert.AreEqual(2, something.BarCount);
}
public class Something : ISomething
{
public Something(IEnumerable<IBar> somethings)
{
this.BarCount = somethings.Count();
}
public int BarCount
{
get; set;
}
}
The full example (including test cases from previous post) can be found on Gist. Definitely need to debug through StructureMap this weekend to understand this behavior better!









Comments