This is the first of a promised series of blog posts to explain and demonstrate the new features of the StructureMap 2.6 release. First, in order to use this feature, you absolutely must be on StructureMap 2.6.1 (or 2.5.4). Your friendly neighborhood Shade Tree Developer introduced a bug into the 2.6.0 codebase that makes this feature screw up the parent container (mea culpa).
I want to start with the new “Nested Container” feature. In a nutshell, the Nested Container is kind of like a temporary clone of a Container that’s invoked like this:
What did I do up above? I simply created a new Container (nested) from an existing Container, then pulled a service from the new nested container, did some work with it, then let the C# “using” block auto magically call the Dispose() method on the new nested container object. You might be asking, why do I need a second Container? Well, the nested container has some special properties:
- The nested container will track all of the transient objects that it creates. When the nested container itself is disposed, it will call Dispose() on any of the transient objects that it created. A normal StructureMap Container does not track the transient objects that it creates (and nor should it IMHO).
- The nested container “pulls” all instances scoped as anything but transients (Singletons, HttpContext scoped objects, ThreadLocalStorage scoped objects, etc.) from the parent container. These objects are not disposed from the nested container.
- “Transient” objects are scoped to the nested container. I’d try to explain that, but why don’t I just show the unit test instead:
It’s not the most exciting thing in the world, but it’s helpful in some specific scenarios:
- Web requests. Inside a single web request I need every object to access the exact same NHibernate ISession instance (substitute the analogue in your persistence tooling of choice). At the end of the web request I may want to tear down and dispose all the services created during that web request – i.e. make damn sure the database connection is closed and cleaned up at the end. I’m not exactly sure how you would use this in ASP.Net MVC (not saying you can’t, just that I haven’t given it much thought), but it’s working out very well for us with a FubuMVC Behavior like I showed here.
- Short lived atomic transactions. We use the nested container within our rules engine. Within a single NHibernate ISession and transaction block, we create several object graphs with service location calls to the nested container.* Using the nested container feature made it much simpler for us to “scope” the ISession and even rules state objects within a logical transaction.
- User Interface composition. From a twitter conversation with Glenn Block a couple weeks back. Let’s say that you have a distinct area of the UI where you have a long running workflow like a wizard that replaces the controls and Presenters / ViewModels currently active. When those Views, ViewModel’s, and Presenters are created, you probably want those objects to have shared state and layout “region manager” type classes injected into them. Using a nested container for the wizard is “a” way to build those objects with the proper shared services.
Most of our nested container usage is wrapped up within the class shown below:
In real usage, we invoke services within a transaction with code like this:
* Some of you are going to read that sentence and do a kneejerk “…but Ayende says you’re only supposed to do one service locator call in the entire application!” Don’t do the kneejerk thing without understanding the context.