Castle Windsor and child containers: Revolutions

Continuing the topic from the previous posts.

What would happen?

Current behavior of Windsor is somewhat flawed. What it will do is it will resolve foo, and provide it with bar. The flaw of this behavior is that now when we resolve foo via any of the tree containers we’ll  get the same instance (since it’s a singleton). This introduced two issues:

  • component from childA (bar) will now be available via childB and parent while logically thinking – it should not.
  • we have temporal coupling in our code. Depending on the order of containers we’ll use to resolve foo we’ll get different results

So what should happen?

Ok, so now that we agreed that current behavior is indeed flawed (we did, didn’t we?) what are our options for fixing it? We basically have two options (both of which were mentioned in comments to previous post).

It all boils down to scoping. If we have a per-web-request object – should single instance be shared among multiple containers or should it be per-web-request-and-per-container? If we have singleton should it be single instance per container, per container hierarchy or per process?

Let’s consider slightly more complicated picture.

containers_2

Now we have two components for bar, one in childA and one in parent. Also we have one more component; baz, which is registered in childB.

classes_2

Baz has dependency on foo, foo still has dependency on bar. All of these dependencies are optional, and all components are singletons.

There can only be one

We want to scope instances strictly per their container. So that foo is scoped in parent (thus visible from its child containers as well), and bar is scoped per childA. This appears to be the simplest setup, and the most in line with definition of singleton, but then we run into problems outlined above.

We then could add another constraint – dependencies can only face upwards the container hierarchy. We would then get foo with its dependency on bar pulled from parent container, consistently, regardless of the container we’d resolve it from. Moreover, we could resolve baz from childB and its dependency would be properly populated from parent since it comes from a container that is higher in the hierarchy, so we’re safe to pull that dependency.

On the other hand this robs us of one of nice (and often used) side effect of child containers, that is contextual overriding of components from containers higher up the hierarchy.

If we have bar in childA, we’d expect to get foo pulled via childA to have that bar, not parent’s bar.

Or perhaps not?

We can approach the problem from another angle altogether. We can narrow down the scope of a component instance, to the scope of its outermost dependency. What do I mean by that?

When resolving foo from childA the outermost dependency of foo would be the bar living in childA. Therefore the instance of foo would have bar pulled from parent, but scoped in childA. Therefore when we’d request foo again, but this time from childB we’d get another instance of foo, with dependency on bar pulled from parent. This could potentially lead to problems as well, since if you’re depending on the fact that single instance of your component will ever live in the application at given point in time you may end up with problems.

So what do you think? Which approach would you prefer, or is there something I’m missing here?

To those who though I’m seriously going to remove support for nested containers rest assured this is not going to happen. I still think this could be a viable option and I wanted to throw it into the air, but its become such a core feature of each IoC container, that Windsor would look crippled if it didn’t have it, regardless of whether or not it’d be actually needed.


Posted 06-04-2010 5:05 AM by Krzysztof Koźmic
Filed under: ,

[Advertisement]

Comments

AndyZ wrote re: Castle Windsor and child containers: Revolutions
on 06-06-2010 10:43 AM

One thing that you need to consider is that we're talking about more than just singletons.  Any non-transient lifestyle will have these issues.

Your first option (dependencies can only face upward in the container hierarchy) seems like a good solution.  If only applied to non-transient items it would still allow for child container item overloading of dependencies in most cases (the safe ones where the items are transient).

One problem with the second approach is that the lifetime of each item must be handled in each child and with something like custom lifestyles this may be problematic.

Perhaps a solution would be to have an additional setting which would be paired with lifestyle to specify the scoping of dependencies and which container owns the resolved object.

Krzysztof Koźmic wrote re: Castle Windsor and child containers: Revolutions
on 06-07-2010 12:53 AM

Andy,

that's basically what commenters on my other blog suggested

kozmic.pl/.../castle-windsor-and-child-containers-empire-strikes-back.aspx

However I feel like this could overcomplicate things too much

Sanele wrote re: Castle Windsor and child containers: Revolutions
on 02-22-2012 3:15 AM

Thanks for your nice cmoemnts, I did build the blog and website but used a service to do it, it is very flexible so I can pretty much make it look like what I want.

Attila wrote re: Castle Windsor and child containers: Revolutions
on 02-23-2012 8:28 PM

I am cempletoly in awe of your organization!  My pantry doesn't have much in it because I'm not sure how much longer we'll be here, but this is great inspiration for when we live somewhere more permanent!

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)