CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

Spring loading your IoC Container

Ayende has a post up this morning called Inverting Inversion of Control where he talks about registering services with an IoC container at runtime.  Ayende is specifically saying that this technique is useful for injecting services that you either can't control the creation of or simply want to construct in another way.  It's funny that he should post this today because I've been using this technique quite a bit the last couple months in my WinForms development.  I'm breaking open the StructureMap code to start a new release today largely to add a bit more support for this scenario.  To add to the discussion, I'll throw out an example of what I'm doing.

 

Registering pieces of the ApplicationShell

In StoryTeller and a couple of my applications at work the ApplicationShell (main form) has grown large and complicated.  It's become advantageous to treat various parts of the main form as separate services of the user interface and let all of them be driven by separate Presenters.  For the sake of consistency with the rest of the application and avoiding nasty Law of Demeter violations, I inject these little pieces of the main form into StructureMap so that StructureMap can instantiate other services that depend on these pieces through constructor arguments.  I could create all of these little user controls and TreeNode's via StructureMap and then call methods to attach them into the ApplicationShell later, but that quickly led to bootstrapping spaghetti code left and right.  It turned out to be much cleaner to use the design time support to place the children controls onto the ApplicationShell form, inject these children into StructureMap, and let StructureMap completely setup the Presenters that depend on these child controls through their constructors.

When I start up StoryTeller the first thing that I do is bootstrap StructureMap's configuration.  The second thing I do is create the main ApplicationShell form.  After the child In the constructor function of ApplicationShell I call the method below to register some of the child controls of ApplicationShell into StructureMap:

        private void loadShellPartsIntoStructureMap()
        {
            ObjectFactory.InjectStub(typeof (IApplicationShell), this);
            ObjectFactory.InjectStub(typeof (IContentPanel), contentPanel);
            ObjectFactory.InjectStub(typeof (IHierarchyNode), hierarchyExplorer.HierarchyNode);
            ObjectFactory.InjectStub(typeof (IFixtureExplorerView), fixtureExplorer);
        }

The "InjectStub()" method was originally put into StructureMap to allow you to override normal StructureMap behavior to push in stubs instead of the normal service during testing.  It does also function correctly in this scenario (in the forthcoming 2.1 version I'm going to add a new method called Inject<T>(T service) ).   Regardless of any other prior configuration, StructureMap will always return the instance passed into InjectStub(Type, object) whenever an instance of the specified Type is requested.  When any other class requests IContentPanel directly or through a constructor function, the "contentPanel" child of ApplicationShell will always be returned.

Now, moving on to see how this works.  I generally use an ApplicationController class to govern the activation and deactivation of screens in the user interface.  The ApplicationController in StoryTeller has a dependency on both the IContentPanel (the tabbing container for screens) and the IHiearchyNode (the top most TreeNode in the navigation tree).  Since we've already injected the two little children into StructureMap, we can completely set up ApplicationController through its constructor.

        public ApplicationController(
            ICommandExecutor executor, 
            IContentPanel panel, 
            IProjectRepository repository,
            ITestEventPublisher publisher, 
            IHierarchyNode hierarchyNode)
        {
            _executor = executor;
            _panel = panel;
            _repository = repository;
            _publisher = publisher;
            _hierarchyNode = hierarchyNode;
        }
 

As long as I create ApplicationController after the StructureMap bootstrapping and the creation of ApplicationShell, I'm ready to go.  Before I switched to the path of injecting the child controls into StructureMap I had a lot more one off bootstrapping code to push around the IContentPanel and IHiearchyNode controls.  By refactoring to the "injected children" mode I cut back on a lot of undesirable coupling and trimmed down some chatty interfaces. 

One of my little maxims of programming is to strive to put everything a class needs into a constructor so that we know the class is ready to go as soon as it's created.  This little trick of spring loading the UI controls into the IoC container gets us closer to that ideal.



Comments

Ivan Krivyakov said:

I remember struggling with Spring and command-line arguments. Creation (or non-creation) of some things dependent on the command line arguments, and I could not find away to "inject" them into the framework. I ended up using hand-written factories.

If I had Inject<T>, this would have solved the problem.

# December 10, 2007 10:46 AM

Weex said:

Hi,

that link storyteller.tigris.org/.../ApplicationController.cs

won't open. It requires some credentials for read access. Could you please change that? So, that curious readers could see what you've linked to :)

# December 10, 2007 11:01 AM

SteveG said:

Glad to see you mention the Law of Demeter - I would rather create specific menthod calls than expose the underlying dependency object.

# December 10, 2007 11:16 AM

pussi » Spring loading your IoC Container said:

Pingback from  pussi &raquo; Spring loading your IoC Container

# December 10, 2007 10:40 PM

Barbricks.Com » Spring loading your IoC Container said:

Pingback from  Barbricks.Com &raquo; Spring loading your IoC Container

# December 11, 2007 3:05 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP