Neal started looking into behaviour of child containers in Windsor. This is an area that’s very rarely used, and as Hammett wrote two years ago – this is speaking with the devil himself. No one really ever uses it so it never got well defined and as Neal found out there are certain inconsistencies, and grey areas there.
This was a don’t ask, don’t tell area, and since Neil opened that can of worms, it’s time to deal with the issue. I’m considering several solutions, and the one I’m leaning towards most would be probably the most controversial.
Remove support for child containers altogether?
Basically handler selectors and sub-resolvers give you all the power you need to handle scenarios where you would want to use child container instead. I think removing the child containers, and add some nicer support for contextual scoping of components would be the best solution.
The point of this post however is to get your thoughts on this issue. Are you using child containers in Windsor? What are you using it for? How are you using it? Write a comment or if you don’t want to share that in public just drop me an email. I’d really like to get a clean picture of how usage of this feature looks like at this point in time, before I make a decision.
I have not had a need for child containers. I wouldn’t have a problem if the feature was removed, especially since it is not consistent.
I’m in favour of removing child containers and properly implementing contextual lifetime scoping.
I tried to mimic Autofac’s contextual scoping using the available public methods. While I got something working (can read on my blog), I had to read Windsor’s code to figure out what would work, and it’s an extremely hacky solution which involves creating child containers on the fly (of which was surprisingly slow).
It would definitely be nice to have this feature directly supported by the container.
Bollocks :/ I’m using them quite extensively. Maybe I can do it differently though – In my app I have a core kernel where all modules are registered, then each module has a private child container from which he has access to the main one and can register some private stuff in there – this way each module (each one of them developed independently), doesn’t have to fear that something is already registered in some other kernel. Additionally, each child kernel has a module-specific data (such as name, author, license information) which is then used to configure such services as logger and so on.
We currently rely heavily on child containers, so I would really hate to seem them go without a good alternative. However, it’s a distinct possibility that there are alternatives, but that we are simply not aware of them.
Here’s what we use child containers for:
One part of our product is essentially one big HHTP handler. It lives inside of APS.NET MVC, but in principle, it could just as well have been one big IHttpHandler.
Thanks to child containers, we have been able to make a very loosely coupled and pluggable architecture, which is super-important because the plugins are the real product – the rest is just a common run-time that hosts the plugin.
However, what our run-time does is that it gathers a lot of contextual information about each request and iteratively registers all this information in a child container before invoking the plugins. Conceptually, this child container is tied to a single request and disposed along with the request.
The reason we use child containers is that we need to be able to fall back to a parent container for all the Singleton-scoped services registered there (e.g. cache). However, we also need to be able to register and dispose request-related services, as these only make sense within a single request. Since we can’t reliably remove services from the container, we need to use a child container.
Plugins are even given the ability to register their own services in the child container. In essense you could say that the container also acts as a Mediator between plugins within the same request. This is not too far from MEF’s ability to let add-ins import and export services at the same time.
It’s possible that there are other alternatives – I’ll have to look into that, but FWIW, this is the reason we currently use child containers.
Ping me if you need further details.
I am in a situation very much like these 2 previous posts. We have our core container which is where our common services are located (cache, email, pub-sub, …) but each module (developed independently) has the ability to register the components they need into a container which can resolve the common services as well as the components that the module itself uses (well, technically there is no manual resolution in the modules, it is all done with property and constructor dependencies, but you get the idea).
We absolutely need the ability to clone the parent container and register services independently of other clones. Whether you call this functionality child containers, clones, copies or something else entirely, I don’t care.
We are using child containers for pretty much the same reasons as above, but specifically what Bill has mentioned.
We have applications with a plug-in style architecture. The application itself is divided into several "contexts" and each context hosts multiple plug-ins. Also, a plug-in can be hosted by multiple "contexts" simultaneously within a single application.
The type and number of contexts is determined by each specialized application, and the plug-ins are loaded dynamically into each context to which they apply.
Keeping all that in mind, we have 3 scopes for components we register:
1. common or "framework" scope: components that are registered in a root
container available to all contexts and all plug-ins.
2. context-specific scope: components that are registered in a context-
specific container (a child of the root container) available only to that
context and its plug-ins.
3. plugin-specific scope: components registered in a plugin-specific
container (a child of a given context-specific container) available only
to that plug-in.
While I think I understand the benefit of being able to provide HandlerSelectors or SubDependencyResolvers, I’m not sure how either of those concepts could replace the use of child containers for what we need to do. Maybe I would just require a more detailed explanation of their potential…
That being said, we too would absolutely require the continued support for child-containers or some other concept that provides us with the same result.
We make extensive use of HandlerSelectors and SubDependencyResolvers to support contextual/dynamic-scoped resolution so we’re probably in the "found other ways to deal with the features that child containers would have provided" camp.
That said, is there a technical reason to drop child container support (e.g., there’s a good reason some of the gray areas remain unopinionated) or is this more about "there are other ways to achieve what child containers would provide and so they simply aren’t needed in Windsor"? Other IoC containers obviously *do* support child containers so I’d just want to ensure that we weren’t losing some important functionality that isn’t available elsewhere in Windsor.
I’m using child containers to temporarily inject a bunch of mock objects into a running server. This allows me to write half an integration test. (test spans from calls on a client API to mocked services running on the webserver).
Its been a blast.